centos平台下
lua-5.1.5(!!!!luabind0.9.1不能支持更高版本的lua。。。)
make linux; 一堆提示libreadline.so的错误
由于lua编译依赖readline库,而其依赖ncurses库,但没有指定,所以出现“未定义的符合引用”错误。需要修改${LUA_DIR}/src/Makefile中linux编译target,在SYSLIBS变量中追加‘-lncurses’选项即可。修改后,如下: linux: $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline -lncurses"
注意, 不是Makefile, 而是src/Makefile。 from:http://blog.csdn.net/sryan/article/details/18033455
make install
cd src && install -p -m 0755 lua luac /usr/local/bin cd src && install -p -m 0644 lua.h luaconf.h lualib.h lauxlib.h lua.hpp /usr/local/include cd src && install -p -m 0644 liblua.a /usr/local/lib cd doc && install -p -m 0644 lua.1 luac.1 /usr/local/man/man1
boost.build(或许可以直接使用boost目录下的bjam或者b2)
cd jam_src; sh build.sh; cp bin/bjam /usr/local/bin/; mkdir /usr/share/boost-build; cp -r ../* /usr/share/boost-build/;
export BOOST_ROOT=...(boost根目录)
export LUA_PATH=/usr/local (注意,lua的头文件在/usr/local/include/下)
bjam --prefix=/usr/local/luabind --toolset=gcc link=static runtime-link=static threading=multi stage debug
bjam --prefix=/usr/local/luabind --toolset=gcc link=static runtime-link=static threading=multi stage release
mkdir -p /usr/local/luabind/include /usr/local/luabind/lib
cp -rf luabind /usr/local/luabind/include/
cp -rf stage/* /usr/local/luabind/lib
简单测试:Scene.h, main.cpp, map.lua
Scene.h
#pragma once #include <string> #include <iostream> #include <vector> extern "C" { #include <lua.h> #include <lualib.h> } #include <luabind/luabind.hpp> class Scene { public: Scene() {} void createObject(int obj); void printObjects(); void loadMap(std::string fileName); private: std::vector<int> mObjects; }; void Scene::createObject( int obj ) { mObjects.push_back(obj); } void Scene::printObjects() { for (std::vector<int>::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) std::cout << (*iter) << std::endl; } void Scene::loadMap( std::string fileName ) { try { using namespace luabind; lua_State* L = lua_open(); luaL_openlibs(L); luabind::open(L); // 导出类Scene module(L) [ // 导出的类名字不必与C++中的一样 // 方法也是这样 // 但是为了看着方便 // 我让它们名称都一样了 class_<Scene>("Scene") .def(luabind::constructor<>()) .def("createObject", &Scene::createObject) .def("printObject", &Scene::printObjects) // 注意到我并没有导出loadMap()方法 ]; // 加载lua文件 luaL_dofile(L, fileName.c_str()); // 调用lua文件中的createScene方法 luabind::call_function<void>(L, "createScene", this); } catch (luabind::error& e) { std::cout << e.what() << std::endl; } }
main.cpp
#include "Scene.h" #include <unistd.h> #include <stdlib.h> int main() { Scene s; s.loadMap("map.lua"); s.printObjects(); return 0; }
- map.lua function createScene( scene ) for i=0, 10 do scene:createObject(i) end end
build:
g++ -g -o test main.cpp -I/usr/local/luabind/include/ -I/usr/local/include/ /usr/local/lib/liblua.a /usr/local/luabind/lib/libluabind.a -ldl
-----new main
#include "Scene.h" #include <unistd.h> #include <stdlib.h> #include <iostream> using namespace std; void testFunc(int k) { cout<<"hello there, i am a cpp fun"<<endl; cout<<"input num:="<<k<<endl; } int main() { <span style="color:#FF0000;">using namespace luabind; lua_State* L = luaL_newstate(); luaopen_base(L); luabind::open(L); module(L, "cppapi") [ def("testFunc", (void(*)(int))testFunc) ]; luabind::module(L) [ // 导出的类名字不必与C++中的一样 // 方法也是这样 // 但是为了看着方便 // 我让它们名称都一样了 class_<Scene>("Scene") .def(luabind::constructor<>()) .def("createObject", &Scene::createObject) .def("printObject", &Scene::printObjects) // 注意到我并没有导出loadMap()方法 ]; </span> Scene s; <span style="color:#FF0000;">// 加载lua文件 luaL_dofile(L, "map.lua"); // 调用lua文件中的createScene方法 luabind::call_function<void>(L, "createScene", &s); luabind::call_function<void>(L, "createScene", &s); //调用两次</span> s.printObjects(); return 0; }
protoc-gen-lua
下载、解压
1)到protobuf目录下, make。 Makefile中使用了pkg-config, 但是lua5.1似乎不支持;因此直接将相关的替换成头文件或者lib文件所在目录就行。得到pb.so
2)plugin目录下, 编写 protoc-gen-lua.sh, 如下:
#!/bin/bash cur=`dirname $0` python $cur/protoc-gen-lua然后增加protoc-gen-lua, protoc-gen-lua.sh的x权限, 都拷贝到/usr/loca/bin/目录下即可
3)到example目录下, 执行:
protoc --proto_path=. --plugin=protoc-gen-lua=/usr/local/bin/protoc-gen-lua.sh --lua_out=./ ./person.proto 其中, --plugin是protoc的参数选项, 格式是NAME=VALUE。 并且VALUE要在可执行文件的searchpath下, 如/bin/, /usr/local/bin等; 本人放在了/usr/local/bin/下。 VALUE不能直接使用protoc-gen-lua文件, protoc中最终是通过execv(VALUE, argv)执行的, 直接传protoc-gen-lua(实际是个python脚本)一直不成功。
c++利用lua实现业务逻辑(主要是修改protobuf类的对象)
1) 绑定protobuf类及其暴漏的public函数到lua中; 在lua脚本中写代码的流程方式与在c++写代码基本一样。
2)不绑定protobuf类及其函数,因为这样比较繁琐(使用代码可以实现程序自动绑定); 因此,将protobuf skema翻译成lua类/表?、以及提供与c++/python等一致的序列化/反序列化机制。c++传递string给lua, lua函数收到后ParseFromString得到lua类,然后再实现业务逻辑; 最后将新对象序列化为string返回给c++。
----lua 新手, 第二种方式总是出错,待查中。
---------continue -------------------------
</pre><pre name="code" class="cpp">//c++ string str; p.set_id(1001); if(p.SerializeToString(&str)) { //TODO, lua内的string类型是TString; 也许modify_string的参数和返回值都是TString, 然后直接lua_bind就成? 暂且不行, 因为lua库和头文件没有暴露TString lua_getglobal(L, "modify_string");//函数到栈顶 lua_pushlstring(L, str.c_str(), str.size());//参数压栈 lua_pcall(L, 1, 2, 0); int len = lua_tonumber(L, -2);//获取两个返回值。 const char *csr = lua_tostring(L, -1); string s2(csr, len); cout <<"s2 .lenght: " << len << endl; Person newp; newp.ParseFromString(s2); cout <<"after modified by lua: id=" << newp.id() << endl; //1889 here... } --lua local person_pb = require "person_pb" local string = string function modify_string(str) local person = person_pb.Person() person:ParseFromString(str) person.id = person.id + 888 local newstr = person:SerializeToString() return string.len(newstr), newstr end --Makefile CXX := g++ OPT := -g -ggdb -Wall CXXFLAGS += -I./ -I/usr/local/include -I/usr/local/luabind/include/ -I/usr/local/include/ -L. CXXFLAGS += $(OPT) LDFLAGS := SHARED_LDFLAGS := -shared SHARED_CFLAGS := -fPIC LIBS := -lprotobuf -ldl -lpb SRCEXTS := .cpp .cc .cxx ##change you want SRCDIRS := ./ SRCS := OBJS := DEPS := BINARY = test SRCS := $(foreach d, $(SRCDIRS), $(wildcard $(addprefix $(d)/*, $(SRCEXTS)))) OBJS := $(foreach x, $(SRCEXTS), $(patsubst %$(x), %.o, $(filter %$(x), $(SRCS)))) DEPS := $(patsubst %.o, %.d, $(OBJS)) all: $(BINARY) $(BINARY):$(OBJS) ifeq ($(strip $(SRCEXTS)), .c) $(CC) $(CFLAGS) -o $(BINARY) $^ $(LDFLAGS) $(LIBS) else $(CXX) $(CXXFLAGS) -o $(BINARY) $^ $(LDFLAGS) $(LIBS) /usr/local/lib/liblua.a /usr/local/luabind/lib/libluabind.a endif obj:$(OBJS) %.o:%.c $(CC) $(CFLAGS) -c -o $@ $< %.o:%.cpp $(CXX) $(CXXFLAGS) -c -o $@ $< %.o:%.cc $(CXX) $(CXXFLAGS) -c -o $@ $< %.o:%.cxx $(CXX) $(CXXFLAGS) -c -o $@ $< clean: rm -rf *.o $(BINARY)