本文主要演示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 <stdio.h>
#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 ?