Lua与C/C++交互――C/C++导出Dll(二)

2014-11-24 12:43:45 · 作者: · 浏览: 1
们要如何调用该Dll呢?首先,把该Dll放到你的Lua能搜寻到的目录——当前目录、Lua安装目录下的clibs目录……然后通过require函数导入。

因为Lua中如果你的函数调用参数只有一个,并且该参数为字符串的话,函数调用时的括号是可以省略的,所以:

require(“YourLibName”)和requir“YourLibName”都是合法的。我们把刚刚生成的WinFeature.dll文件拷贝到C盘下,然后在C盘启动Lua。示例如下:

\

可以看到,函数调用方式都是“包名.函数名”,而包名就是你的Dll的名字。我们可以用下面的方式查看一个包中的所有函数:

for k, v in pairs(PackageName) do

print(k, v)

end

然后我们调用WinFeature.ShowMsgBox函数:

\

4.Lua堆栈详解

唔,那么lua_State结构如何管理Lua运行环境的呢?Lua又是如何将参数传递到C/C++函数的呢?C/C++函数又如何返回值给Lua呢?……这一切,都得从Lua堆栈讲起。

Lua在和C/C++交互时,Lua运行环境维护着一份堆栈——不是传统意义上的堆栈,而是Lua模拟出来的。Lua与C/C++的数据传递都通过这份堆栈来完成,这份堆栈的代表就是lua_State*所指的那个结构。

4.1.堆栈结构解析

堆栈通过lua_push系列函数向堆栈中压入值,通过luaL_check系列从堆栈中获取值。而用luaL_check系列函数时传递的参数索引,比如我们调用WinFeature.ShowMsgBox(“Hello”, “Tip”)函数时,栈结构如下:

\

其中,参数在栈中的索引为参数从左到右的索引(从1开始),栈顶元素索引也可以从-1记起。栈中元素个数可以用lua_gettop来获得,如果lua_gettop返回0,表示此栈为空。(lua_gettop这个函数名取得不怎么样!呵呵)

4.2.提取参数

luaL_check系列函数在获取值的同时,检测这个值是不是符合我们所期望的类型,如果不是,则抛出异常。所有这个系列函数如下:

luaL_checkany ——检测任何值(可以为nil)

luaL_checkint ——检测一个值是否为number(double),并转换成int

luaL_checkinteger ——检测一个值是否为number(double),并转换成lua_Integer(prtdiff_t),在我的机子上,ptrdiff_t被定义为int

luaL_checklong ——检测一个值是否为number(double),并转换成long

luaL_checklstring ——检测一个值是否为string,并将字符串长度传递在[out]参数中返回

luaL_checknumber ——检测一个值是否为number(double)

luaL_checkstring ——检测一个值是否为string并返回

luaL_checkudata ——检测自定义类型

4.3.传递返回值

当我们要传递返回值给Lua时,可以用lua_push系列函数来完成。每一个导出函数都要返回一个int型整数,这个整数是你的导出函数的返回值的个数。而返回值通过lua_push系列函数压入栈中。比如一个Add函数:

extern “C” int Add(lua_State* luaEnv)

{

CheckParamCount(luaEnv, 2);

double left = luaL_checknumber(luaEnv, 1);

double right = luaL_checknumber(luaEnv, 2);

double result = left + right;

lua_pushnumber(luaEnv, result);

return 1;

}

可以看出,我们用lua_pushnumber把返回值压入栈,最后返回1——1代表返回值的个数。lua_push系列函数如下:

lua_pushboolean ——压入一个bool值

lua_pushcfunction ——压入一个lua_CFunction类型的C函数指针

lua_pushfstring ——格式化一个string并返回,类似于sprintf

lua_pushinteger ——压入一个int

lua_pushlightuserdata ——压入自定义数据类型

lua_pushliteral ——压入一个字面值字符串

lua_pushlstring ——压入一个规定长度内的string

lua_pushnil ——压入nil值

lua_pushnumber ——压入lua_Number(double)值

lua_pushstring ——压入一个string

lua_pushthread ——压入一个所传递lua_State所对应的线程,如果此线程是主线程,则返回1

lua_pushvalue ——将所传递索引处的值复制一份压入栈顶

lua_pushvfstring ——类似lua_pushfstring

通过这些函数,我们可以灵活的使用C/C++的高性能特性,来导出函数供Lua调用

摘自:Arnozhang的专栏