【Lua 语言】Lua 调用 C 函数

Lua 提供了调用 C 函数的接口,这样我们可以开心地用 C 来写一些底层的代码供 Lua 调用了。这里将整个流程整理一下。

1. 在 C 模块定义好函数

新建 C 源文件,将需要被 Lua 调用的函数实现一下,这里实现一个简单的传值函数。

/**
 * 简单地对传入参数加 1,并返回结果
 */
int l_plus_one(lua_State *L)
{
    // 获取函数参数:从栈底取一个参数
    long long k = lua_tointeger(L, 1);
    
    // 函数主体:做加 1 操作
    ++k;
    
    // 函数结果返回:将结果压进栈顶
    lua_pushinteger(L, k);
    
    // 函数结果返回:表示在从栈顶算起,有 1 个值是返回值
    return 1;
}

上面有几点需要注意

* 函数的原型是固定的:int (*l_func)(lua_State*)

* 返回类型为 int,表示在 lua 中调用该函数时获得的返回值个数

* 函数参数 lua_State,lua 和 C 通信时用到的上下文

* lua 模块在调用的 C 函数时,每一个函数都分配了一个在 C 和 Lua 之间传递参数的栈,用作参数和返回值传递用。

2. 在 C 模块导出该函数

假设我们的 C 模块文件名叫做 mylib

/**
 * 函数集的结构体
 */
struct luaL_Reg funcs[] =  
{  
    { "plus_one", l_plus_one },
    { NULL, NULL }
};  


/**
 * Lua 模块默认调用的初始化函数
 */
__declspec(dllexport) int luaopen_mylib(lua_State *L)  
{
    // 在栈中新建一个表
    lua_newtable(L);
    
    // 将函数存入表中
    luaL_setfuncs(L, funcs, 0);
    
    // 表示 Lua 端能收到一个返回值,即这个表
    return 1;  
}  

* 我们一定要在 C 模块中定义 int luaopen_mylib(lua_State*) 这个函数名的函数,因为 lua 加载 C 模块时会自动调用它

* 这个函数是两个模块交互的关键。在这个函数里面,我们使用 Lua 提供的那些 capi 来往栈里放任何东西,Lua 端就可以取到了

* 这里我们当然是放上面的那个函数了

* 在老版本下 (5.2以下)我们会直接在这个函数中加载上面写的那个函数到全局空间中。可以参考这里 点击打开链接

在 luaopen_mylib 函数中写好到处部分后,我们需要将 C 源文件编译成动态库给 Lua 加载,windows 下把项目类型设置成 dll 再编译就行了。

3. 在 Lua 模块中使用

Lua 中使用

local l = require "mylib"

* Lua 模块调用时会搜索 cpath 中的 mylib.dll(Windows)/mylib.so(Linux),并加载到内存中

* Lua 模块会调用动态库中的 luaopen_mylib 函数一次,这些都是默认好的

按照我们上面 luaopen_mylib 这个函数的写法,返回结果应该是一个,是存放函数集的表,我们把它赋值给 l。

调用函数

local ret = l.plus_one(2)

如果调用成功的话 ret 值应该是 3 了

运行环境:windows/lua 5.3/msvc 11.0

你可能感兴趣的:(【Lua 语言】Lua 调用 C 函数)