当前位置: 首页 > 工具软件 > LuaBind > 使用案例 >

主c++ 辅lua luabind protobuf

梁研
2023-12-01

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

- 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)
                             










 类似资料: