本文介绍如何在lua中如何调用自定义C语言函数
1 C函数要求
Lua可以调用C语言函数,但这并不意味着Lua可以调用所有的C函数。当Lua调用C函数时,这个C函数必须遵循某种规则来获取参数和返回结果。此外,当Lua调用C函数时,我们必须注册该函数,即必须以一种恰当的方式为Lua提供该C 函数的地址。所有在lua中注册的函数必须遵循下面原型。
typedef int (*lua_CFunction) (lua_State * L);
举例如下,
// 定义C函数,参数必须为lua_State* L状态,
// 返回值为lua函数test的返回值数量,为0.
static int test( lua_State* L){
printf("使用lua调用C函数test成功\n");
return 0;
}
2 注册一个C函数
定义好一个C函数后,需使用lua_register函数进行注册后,才能在lua语言中使用。lua_register格式要求如下。
void lua_register (lua_State *L, const char *name, lua_CFunction f);
举例如下,
//04注册一个C函数.c
#include <stdio.h>
#include <stdlib.h>
// Lua数据类型与函数接口
#include "lua.h"
// Lua与C交互辅助函数接口
#include "lauxlib.h"
// Lua标准库打开接口
#include "lualib.h"
// 定义C函数,参数必须为lua_State* L状态,
// 返回值为lua函数test的返回值数量,为0.
static int C_test( lua_State* L){
printf("使用lua调用C函数C_test成功\n");
return 0;
}
int main()
{
// 创建Lua状态
lua_State* L = luaL_newstate();
// 打开标准库
luaL_openlibs(L);
// 注册C函数test为lua函数test
lua_register(L,"test",C_test);
// 解析并执行Lua脚本字符串
luaL_dostring(L,"test()");
// 关闭Lua线程
lua_close(L);
return 0;
}
运行结果如下,
3 C语言与lua语言参数传递
上面例子中lua语言调用C函数test,中间没包含参数传递,即函数test既没有参数输入也没有返回值,比较简单。C语言与lua语言参数传递需使用到虚拟栈 lua_State* L进行交换。举例如下,
lua调用
-- add为一个用C函数C_add定义的函数
-- 当在lua执行下面函数add时,lua语言会将参数7,2,5按顺序压入虚拟栈L,再调用C函数C_add,
-- 后根据C函数C_add的返回值,将栈顶弹出传递给lua语言,赋值给变量a
a=add(7,2,5)
C函数C_add定义如下
// 定义C函数,参数必须为lua_State* L状态
static int C_add( lua_State* L){
printf("使用lua调用C函数C_add成功\n");
//使用lua_tointeger按索引获取栈L的元素
//索引1为函数参数1,2为函数参数2,以此类推.
//lua传递参数给C语言需进行数据转换,
//因为这个函数参数均为整数,所以使用lua_tointeger
//若其他数据类型,需使用类似的lua_to*函数
int a1 = lua_tointeger(L,1);
int a2 = lua_tointeger(L,2);
int a3 = lua_tointeger(L,3);
//打印各个参数的值
printf("第1个参数=%d\n",a1);
printf("第2个参数=%d\n",a2);
printf("第3个参数=%d\n",a3);
//将三个参数值相加并压入栈
//使用lua_pushinteger函数将整数值压入,其他数据类型需使用类似lua_push*函数
//若有多个返回值,按顺序压入栈
lua_pushinteger(L,a1+a2+a3);
// 返回值为lua函数add的返回值数量,为1.
return 1;
}
整理成C代码
//05lua和C语言参数传递.c
#include <stdio.h>
#include <stdlib.h>
// Lua数据类型与函数接口
#include "lua.h"
// Lua与C交互辅助函数接口
#include "lauxlib.h"
// Lua标准库打开接口
#include "lualib.h"
// 定义C函数,参数必须为lua_State* L状态
static int C_add( lua_State* L){
printf("使用lua调用C函数C_add成功\n");
//使用lua_tointeger按索引获取栈L的元素
//索引1为函数参数1,2为函数参数2,以此类推.
//lua传递参数给C语言需进行数据转换,
//因为这个函数参数均为整数,所以使用lua_tointeger
//若其他数据类型,需使用类似的lua_to*函数
int a1 = lua_tointeger(L,1);
int a2 = lua_tointeger(L,2);
int a3 = lua_tointeger(L,3);
//打印各个参数的值
printf("第1个参数=%d\n",a1);
printf("第2个参数=%d\n",a2);
printf("第3个参数=%d\n",a3);
//将三个参数值相加并压入栈
//使用lua_pushinteger函数将整数值压入,其他数据类型需使用类似lua_push*函数
//若有多个返回值,按顺序压入栈
lua_pushinteger(L,a1+a2+a3);
// 返回值为lua函数add的返回值数量,为1.
return 1;
}
int main()
{
// 创建Lua状态
lua_State* L = luaL_newstate();
// 打开标准库
luaL_openlibs(L);
// 注册C函数C_add为lua函数add
lua_register(L,"add",C_add);
// 解析并执行Lua脚本字符串
luaL_dostring(L,"
-- add为一个用C函数C_add定义的函数
-- 当在lua执行下面函数add时,lua语言会将参数7,2,5按顺序压入虚拟栈L,再调用C函数C_add,
-- 后根据C函数C_add的返回值,将栈元素弹出传递给lua语言,赋值给变量a
-- add函数功能是将三个参数进行相加
a=add(7,2,5)
print('a=',a) -->14
");
// 关闭Lua状态
lua_close(L);
return 0;
}
运行结果如下