为Lua5.2.2编写C模块

<p>本文的环境是win7和VS2010:</p> <p>1.首先到官网下载lua5.2.2源码包,并且在VS2010上新建空工程比如命名LuaCons,将源码包中的头文件和源文件都添加进去。</p> <p>2.需要生成lua的动态链接库,首先去掉源文件中的lua.c,并且在vs中的属性-&gt;常规-&gt;配置类型,修改为动态库(.dll),并且在</p> <p>属性-&gt;C/C++-&gt;预处理器中,添加预定义LUA_COMPAT_ALL和LUA_BUILD_AS_DLL,当然这些预定义可以在luaconf.h中</p> <p>开头定义好,不过我不怎么喜欢修改自带文件的方式。</p> <p>3.右键生成,于是在Debug中可以看到生成的LuaCons.dll和LuaCons.lib。</p> <p>4.新建C模块工程(怕麻烦就在同一个解决方案中即可)比如命名为mylib。在C/C++-&gt;常规-&gt;附加包含目录中填上指向解压后的src路径</p> <p>比如相对路径../xxxx/src或者绝对路径D:/xxxx/src,在链接器-&gt;常规-&gt;附加库目录中填上直到刚才生成的动态库路径,</p> <p>相对或者绝对的都可以比如D:/xxxx/Debug。在链接器-&gt;输入-&gt;附加依赖项中添加LuaCons.lib。</p> <p>5.在模块工程中新建mylib.h和mylib.cpp文件,填上:</p> <p>mylib.h文件:</p> <p>#ifndef _MYLIB_H <br />#define _MYLIB_H</p> <p>extern &quot;C&quot; <br />{ <br />#include &quot;lua.h&quot; <br />#include &quot;lualib.h&quot; <br />#include &quot;lauxlib.h&quot; <br />};</p> <p>extern &quot;C&quot; int __declspec(dllexport) luaopen_mylib(lua_State *L);</p> <p>#endif //_MYLIB_H</p> <p>由于使用C++编译器,所以lua的三个头文件需要以extern “C”扩起来。并且导出函数入口点必须是luaopen_xxx,</p> <p>其中xxx就是要生成C模块(dll)库的名字。</p> <p>mylib.cpp文件:</p> <p>#include &quot;mylib.h&quot;</p> <p>//说明:lua的交换栈,栈底部为1,向栈顶递增;也可认为栈顶部为-1,向栈底部递减</p> <p>//演示返回多个参数 <br />extern &quot;C&quot; static int l_mystr(lua_State *L) <br />{ <br />&#160;&#160;&#160; lua_pushstring(L, &quot;looyer&quot;);//返回的第一个参数, 字符串“looyer” <br />&#160;&#160;&#160; lua_pushnumber(L, 37);//返回的第二个参数,数字37</p> <p>&#160;&#160;&#160; //返回第三个参数table = {['ac'] = 17, [2] = &quot;bn&quot;} <br />&#160;&#160;&#160; lua_newtable(L);//在栈顶创建一个table</p> <p>&#160;&#160;&#160; //方法一,设置table的键和值 <br />&#160;&#160;&#160; lua_pushstring(L, &quot;ac&quot;); <br />&#160;&#160;&#160; lua_pushnumber(L, 17); <br />&#160;&#160;&#160; lua_settable(L, -3);//在table中设置键值对['ac'] = 17, 设置后,自动pop掉栈顶的两个元素</p> <p>&#160;&#160;&#160; //方法二,设置table的键和值 <br />&#160;&#160;&#160; lua_pushstring(L, &quot;bn&quot;); <br />&#160;&#160;&#160; lua_setfield(L, -2, &quot;2&quot;);//将栈顶元素设置为键“2”的值,并且赋个索引为-2的栈中table</p> <p>&#160;&#160;&#160; return 3;//返回参数的个数 <br />}</p> <p>//演示输入多个参数,检查输入一个数字,一个字符串,一个table <br />extern &quot;C&quot; static int l_myadd(lua_State *L) <br />{ <br />&#160;&#160;&#160; int a = luaL_checknumber(L, 1); <br />&#160;&#160;&#160; const char *p = luaL_checkstring(L, 2); <br />&#160;&#160;&#160; lua_getfield(L, 3, &quot;yt&quot;);//将第三个参数table的“yt”键的值压入栈 <br />&#160;&#160;&#160; int b = luaL_checknumber(L, -1);//取出该“yt”键的值 <br />&#160;&#160;&#160; lua_pushnumber(L, a + b); <br />&#160;&#160;&#160; return 1;//返回一个参数 <br />}</p> <p>static const struct luaL_Reg mylib[] = <br />{ <br />&#160;&#160;&#160; {&quot;mystr&quot;, l_mystr}, <br />&#160;&#160;&#160; {&quot;inadd&quot;, l_myadd}, <br />&#160;&#160;&#160; {NULL, NULL} <br />};</p> <p>int luaopen_mylib(lua_State *L) <br />{ <br />&#160;&#160;&#160; luaL_newlib(L, mylib); <br />&#160;&#160;&#160; return 1; <br />}</p> <p>6.点击生成,即可看到Debug库中生成了mylib.dll和mylib.lib,我们只需要mylib.dll即可。</p> <p>7.在lua中调用我们写好的dll模块,首先在LuaCons工程中添加刚刚移除的lua.c文件,然后移除luac.c文件,记住不要去掉刚才定义的两个宏,</p> <p>否则待会在lua中加载会失败,特别是去掉LUA_BUILD_AS_DLL会在loadlib.c中的ll_load函数中的WIN32函数LoadLibraryExA中发生加载错误,</p> <p>其错误待会为193-<strong>ERROR_BAD_EXE_FORMAT</strong>,不知为什么,留着以后调试吧。</p> <p>8.将LuaCons工程的类型从dll改回生成应用程序的形式。生成即可。</p> <p>9.尝试加载刚刚写的C模块,假如mylib.dll和LuaCons.exe在同一个文件夹下,运行如下:</p> <p><a href="http://static.oschina.net/uploads/img/201305/01155012_F3Rm.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://static.oschina.net/uploads/img/201305/01155017_VMlY.png" width="614" height="301" /></a></p> <p>假如mylib.dll和LuaCons.exe不在同一个文件夹下,只需要修改package.cpath即可,比如mylib.dll在D:\Lib中只需要在require之前添加</p> <p>package.cpath = package.cpath .. “;D:\\Lib\\?.dll”即可。</p> <p>后记,关于Lua的更多的知识,我还需要多多学习,开始时也是错误多多,后面跟着程序调试就好了。Play Happy!~</p>

猜你喜欢

转载自my.oschina.net/u/146803/blog/126772
今日推荐