Lua调用只有头文件的C++动态库函数
2014-10-15 22:16
585 查看
前段时间公司让我寻找一个for C++的Lua Binder库,要求C++ 和 Lua能够双向调用(所以SWIG/tolua排除),最后选择了LuaBind的一个fork,名叫LuaPonte,选择的原因是既有LuaBind的广泛使用比较可靠,又支持LuaJIT(我们要用)的5.1语法。
昨天做summary presentation时我用这个例子展示Lua调C++的效果
没想到被人challenge了,说print_hello函数是自己定义的,实际项目中很可能不知道函数的定义,这时你怎么保证还能调用?
当时没反应过来,我选的LuaPonte也被architect枪毙掉了。。。。。。
今天仔细了解了下Lua调C的方法,总结起来就是
1,假设你的库里有n个函数,库名libxxx.so,则必须提供一个函数
2,在luaopen_xxx里调用luaL_Register注册你的所有n个函数
3,其中每个函数都必须是lua_CFunction类型
4,每个lua_CFunction获取Lua通过栈传入的参数,计算后将结果通过栈传回Lua
网上给的很多lua_CFunction示例,基本都是这样
但是这样很难自动化,如果只能这样则SWIG就不可能存在了,所以,我猜测上面的代码如果要自动生成的话,应该是这样的
这样就将负责bind的myAdd和负责运算的trueAdd分离开来。
其实这个trueAdd完全可以放在第三方库里,由LuaPonte(或其他Binder库)根据trueAdd的签名(头文件)生成myAdd,然后主程序链接myAdd,myAdd又链接trueAdd。
估计SWIG也是这么个路子,只是SWIG要额外产生一个so,相比之下该方法更好。
最后上一个自己写的例子
test.cpp
libtest.cpp
Makefile
注意:若运行报找不到libtest.so,一般是LD_LIBRARY_PATH没有加入当前目录,加入即可。
昨天做summary presentation时我用这个例子展示Lua调C++的效果
void print_hello(int number) { std::cout << "hello world " << number << std::endl; } int main() { // Create a new lua state lua_State *myLuaState = luaL_newstate(); // Connect LuaBind to this lua state luabind::open(myLuaState); // Add our function to the state's global scope luabind::module(myLuaState) [ luabind::def("print_hello", print_hello) ]; // Now call our function in a lua script luaL_dostring( myLuaState, "print_hello(123)\n" ); lua_close(myLuaState); }
没想到被人challenge了,说print_hello函数是自己定义的,实际项目中很可能不知道函数的定义,这时你怎么保证还能调用?
当时没反应过来,我选的LuaPonte也被architect枪毙掉了。。。。。。
今天仔细了解了下Lua调C的方法,总结起来就是
1,假设你的库里有n个函数,库名libxxx.so,则必须提供一个函数
2,在luaopen_xxx里调用luaL_Register注册你的所有n个函数
3,其中每个函数都必须是lua_CFunction类型
4,每个lua_CFunction获取Lua通过栈传入的参数,计算后将结果通过栈传回Lua
网上给的很多lua_CFunction示例,基本都是这样
int myAdd(lua_State *L) { int a = lua_getinteger(L, 1);// 1st arg int b = lua_getinteger(L, 2);// 2nd arg lua_pushinteger(L, a+b); //return sum to lua return 1; // return result num }
但是这样很难自动化,如果只能这样则SWIG就不可能存在了,所以,我猜测上面的代码如果要自动生成的话,应该是这样的
int myAdd(lua_State *L) { //根据类型推导库(boost::any等)获得参数个数和类型,略 int arg1 = lua_getinteger(L, 1);// 1st arg int arg2 = lua_getinteger(L, 2);// 2nd arg int result1 = trueAdd(arg1, arg2); //the wrapped func! lua_pushinteger(L, result1); //return sum to lua return 1; // return result num }
这样就将负责bind的myAdd和负责运算的trueAdd分离开来。
其实这个trueAdd完全可以放在第三方库里,由LuaPonte(或其他Binder库)根据trueAdd的签名(头文件)生成myAdd,然后主程序链接myAdd,myAdd又链接trueAdd。
估计SWIG也是这么个路子,只是SWIG要额外产生一个so,相比之下该方法更好。
最后上一个自己写的例子
test.cpp
#include <luaponte/luaponte.hpp> extern int myAdd(int a, int b);//all from third party lib's header file int main() { // Create a new lua state lua_State *myLuaState = lua_open(); // Connect LuaBind to this lua state luaponte::open(myLuaState); luaponte::module(myLuaState)[ luaponte::def("myAdd", myAdd) ]; std::cout << "Result: " << luaponte::call_function<int>(myLuaState, "myAdd", 2, 3) << std::endl; lua_close(myLuaState); return 0; }
libtest.cpp
int myAdd(int a, int b) { return a+b; }
Makefile
all: g++ -fPIC -c libtest.cpp -o libtest.o g++ -shared -o libtest.so libtest.o -ldl g++ -std=c++11 -c test.cpp -o test.o -I/root/pkgs/luaponte-master/ g++ -o test -L/usr/local/lib -L/root/pkgs/luaponte-master/build/src/ -L. test.o -ltest -lluaponte -llua clean: rm -f *.o *.so test
注意:若运行报找不到libtest.so,一般是LD_LIBRARY_PATH没有加入当前目录,加入即可。
相关文章推荐
- lua脚本调用C++动态库中的函数
- C/C++中调用LUA函数
- C++调用lua函数的一种通用办法
- 简答的lua调用c++函数例子
- C++调用Lua的函数
- (如何在C++代码中调用Lua脚本的函数?)
- c++调用lua函数
- C/C++中调用LUA函数
- 解决c++ 调用lua 方式! 避免重复写逻辑对应的lua 函数
- 如何在c/c++中调用LUA函数
- 【木头Cocos2d-x 031】Lua篇(第06章):Lua调用C++的函数
- 在Lua中调用c++函数示例
- tolua++绑定C/C++语言函数供lua调用
- C++继承中构造函数、析构函数调用顺序及虚函数的动态绑定
- 069 - 问,lua程序设计(第四部分)笔记三,c++调用lua函数 - everettjf - C++博客
- VC6.0配置LUA编译环境及LUA调用C++函数的简单示例
- C/C++中调用LUA函数(zz)
- C++保存和调用lua函数
- lua学习(三)--------lua调用c++函数和简单的错误处理
- lua调用C++函数崩溃时,查看lua的调用栈信息 (特别适用于tolua++)