#Lua5.3简单的C扩展示例以及与OpenResty(LuaJIT)的兼容编译 [上篇文章](../LuaJIT_C_Extend_LuaSQL_complier_connect_Access/detail.html "上篇文章")在`OpenResty`的`LuaJIT`环境下编译了`简单的C扩展示例`和`LuaSQL`,这次我们在标准的`Lua官方标准版本Lua5.3`下编译这个C扩展…… 之所以没有随着上一篇文章中写出来,而是采用另发一篇博文来补充的原因是……我刚刚才编译并测试成功…… 编译时总是报`luaL_register`的`reference`找不到……我看了一下`lua`导出的函数中,确实找不到这个函数了…… 这个函数可能是在`Lua 5.1`中有,但是在`Lua 5.3`中去掉了……这可怎么办? 我参考了`LuaSQL-odbc`的实现,发现它没有调`register`,而是直接返回一个表就行了…… 我参照`LuaSQL-odbc`注册的实现,修改了上篇文章中提到的的`hello.c`: ```C #include "lua.h" #include "lauxlib.h" #include "lualib.h" static const char* dohello(const char* src) { printf(src); return "I'm OK!"; } static int l_hello(lua_State* lua) { const char *src = NULL; src = luaL_checkstring(lua, 1); //出栈获取源字符串 const char * des = dohello(src); //something lua_pushstring(lua, des); //压栈返回给lua return 1; //告诉lua返回了一个变量 } //映射表,"doHello"为lua中的函数名,l_hello为真正C中的函数地址 static const struct luaL_Reg libhello[] = { {"doHello", l_hello}, {NULL, NULL}, }; //模块注册函数 int luaopen_hello(lua_State* lua) { //注册本模块中所有的功能函数,hello为模块名,libhello数组存储所有函数的映射关系 //luaL_register(lua, "hello", libhello); lua_newtable (lua); luaL_setfuncs (lua, libhello, 0); return 1; } ``` 其实只改了一处,那就是把`luaL_registe`r改成了一个带函数成员的表了…… 当然,还是在`MinGW`环境下编译命令: ```Shell gcc lua53.dll hello.c --share -o hello.dll ``` 编译出`hello.dll`文件…… 测试效果如何呢?打开`lua.exe`略微试了一下,感觉还不错: ``` Lua 5.3.3 Copyright (C) 1994-2016 Lua.org, PUC-Rio > hello = require("hello") > r = hello.doHello("run~~~~\n") run~~~~ > print(r) I'm OK! > for k,v in pairs(hello) do print(k..":"..tostring(v)) end doHello:function: 6240126c ``` 那么返回头来,再将这种写法放回`OpenResty`的`luaJIT`中编译看看如何? 那么,还是`MinGW`,把`hello.c`放入`OpenResty`目录中(把上次的删掉),执行编译 ```Shell gcc lua51.dll hello.c --share -Iinclude\luajit-2.1 -o hello.dll ``` 结果发现又报找不到`luaL_setfuncs`的引用……我又用资源编辑器打开`lua51.dll`看了一下,发现果然没有这个函数…… 那么原来的`LuaSQL`是如何编译成功的呢?结果我再次查看`LuaSQL`的源码,发现了`luaL_setfuncs`函数的定义,看了一下宏,原来`5.1版本`**没有**这个函数,这个函数是从`5.2`**开始加上**的……而这个函数的实现也是从`5.2`中拷出来的……那么我们加入这一段后再次编译`hello.c` : ```C #if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 /* ** Adapted from Lua 5.2.0 */ void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; lua_pushstring(L, l->name); for (i = 0; i < nup; i++) /* copy upvalues to the top */ lua_pushvalue(L, -(nup + 1)); lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ lua_settable(L, -(nup + 3)); } lua_pop(L, nup); /* remove upvalues */ } #endif ``` 这次终于编译成功了~当然输出结果是几乎一样的: ``` LuaJIT 2.1.0-beta2 -- Copyright (C) 2005-2016 Mike Pall. http://luajit.org/ JIT: ON SSE2 SSE3 SSE4.1 fold cse dce fwd dse narrow loop abc sink fuse > hello = require("hello") > r = hello.doHello("run~\n") run~ > print(r) I'm OK! > for k,v in pairs(hello) do print(k..":"..tostring(v)) end doHello:function: 0x004c7cc8 ``` 然后再把修改后的`hello.c`返回来放到`Lua5.3`中编译测试,一样能够成功,不再重复描述了…… 这样终于能将`Lua5.3`和`OpenResty`的`LuaJIT`的C扩展库兼容了…… 分享出来,希望大家的研究过程能比我更顺利……


发表评论

必填,公开,这样称呼起来方便~

必填,不会被公开,不必担心~

http://

非必填,公开,目的是方便增进友好访问~

必填,请输入下方图片中的字母或数字,以证明你是人类

看不清楚
必填,最好不要超过500个字符
     ↑返回顶端↑