本文主要演示Lua脚本调用C程序的基本实现方法,并解决实践过程中遇到的问题。
系统环境:CentOS 6.5
Linux HLZ 2.6.32-431.el6.i686 #1 SMP Fri Nov 22 00:26:36 UTC 2013 i686 i686 i386GNU/Linux
Lua开源软件版本:lua-5.3.4.tar.gz
特别说明,由于lua-5.1.x版本与后续版本的接口函数的差异较大,为保证本文提供小程序可直接在你本地调试通过,请安装5.2以及后续版本的Lua开源软件。
Lua开源软件下载和安装方法,可参考另一篇博文:
http://blog.csdn.net/hanlizhong85/article/details/74025244
1、Lua脚本调用C程序
1.1、C程序实现(math.c):
#include
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
static int c_add(lua_State *L)
{
int a, b;
a = lua_tonumber(L, 1);
b = lua_tonumber(L, 2);
lua_pushnumber(L, a + b);
return 1;
}
static int c_sub(lua_State *L)
{
int a, b;
a = lua_tonumber(L, 1);
b = lua_tonumber(L, 2);
lua_pushnumber(L, a - b);
return 1;
}
static const struct luaL_Reg reg_libs[] =
{
{"lua_add", c_add},
{"lua_sub", c_sub},
{NULL, NULL}
};
int luaopen_clibs(lua_State *L)
{
lua_newtable(L);
luaL_setfuncs(L, reg_libs, 0);
//luaL_register(L, "clibs", reg_libs);
return 1;
}
1.2、Lua脚本实现(math.lua):
local clibs = require("clibs")
c =clibs.lua_add(10, 20) --调用c中注册的函数lua_add
d =clibs.lua_sub(99, 33)
print("c= ", c)
print("d= ", d)
1.3、把C文件编译成动态库文件:
[root@HLZlua_c]# gcc -fPIC -shared -o clibs.so math.c
[root@HLZlua_c]# ls
math.lua clibs.so math.c
1.4、执行lua程序:
[root@HLZlua_c]# lua math.lua
c= 30.0
d= 66.0
2、常见错误及解决方法:
2.1、C程序math.c的 luaopen_clibs 函数必须满足命名规则,即固定前缀 luaopen_ +动态库名(不包含后缀.so)
譬如本文的C源文件中,原来注册函数命名为int lua_clibs_reg(lua_State *L),在执行lua程序报了符号未定义错误:
[root@HLZlua_c]# gcc -fPIC -shared -o clibs.so math.c
[root@HLZlua_c]# lua math.lua
lua:error loading module 'clibs' from file './clibs.so':
./clibs.so: undefined symbol:luaopen_clibs
stack traceback:
[C]: in ?
[C]: in function 'require'
math.lua:3: in main chunk
[C]: in ?
2.2、C程序math.c的luaopen_clibs函数中,用luaL_setfuncs注册而非luaL_register
用luaL_register编译&链接均不报错,但是执行math.lua脚本时,会报如下错误(可能是与lua版本有关,新版本5.3.4的lua库中没有luaL_register接口了):
[root@HLZlua_c]# gcc -fPIC -shared -o clibs.so math.c
[root@HLZlua_c]# lua math.lua
lua:error loading module 'clibs' from file './clibs.so':
./clibs.so: undefined symbol:luaL_register
stacktraceback:
[C]: in ?
[C]: in function 'require'
math.lua:3: in main chunk
[C]: in ?
2.3、Lua脚本中require加载so文件返回的对象应保存下来,否则执行lua脚本会报错
用local clibs = require("clibs"),而非require("clibs"):
[root@HLZlua_c]# lua math.lua
lua:error loading module 'clibs' from file './clibs.so':
./clibs.so: undefined symbol:luaopen_clibs
stacktraceback:
[C]: in ?
[C]: in function 'require'
math.lua:2: in main chunk
[C]: in ?