? ? ? lua是一門語法簡單饺窿,效率很高的腳本語言歧焦,能夠很方便的與C語言交互,很適合做膠水語言使用肚医,本文內(nèi)容有兩部分绢馍,第一部分講如何在C語言中調(diào)用lua,第二部分講如何在lua中調(diào)用C語言模塊肠套。
1.在C語言中調(diào)用lua
? ? ?在C語言中調(diào)用lua要用到lua提供的C語言接口舰涌,test.c示例代碼如下,linux下編譯指令:
? ? ? gcc ?test.c ?-o ?test ? ?/usr/local/lib/liblua.a ? -lm ? -ldl
? ? 然后輸入 ./test 即可運行生成的可運行文件 test
#include <stdio.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
//待Lua調(diào)用的C注冊函數(shù)你稚。
static int add2(lua_State* L)
{
? ? //檢查棧中的參數(shù)是否合法瓷耙,1表示Lua調(diào)用時的第一個參數(shù)(從左到右),依此類推刁赖。
? ? //如果Lua代碼在調(diào)用時傳遞的參數(shù)不為number搁痛,該函數(shù)將報錯并終止程序的執(zhí)行。
? ? double op1 = luaL_checknumber(L,1);
? ? double op2 = luaL_checknumber(L,2);
? ? //將函數(shù)的結(jié)果壓入棧中宇弛。如果有多個返回值鸡典,可以在這里多次壓入棧中。
? ? lua_pushnumber(L,op1 + op2);
? ? //返回值用于提示該C函數(shù)的返回值數(shù)量枪芒,即壓入棧中的返回值數(shù)量彻况。
? ? return 1;
}
//另一個待Lua調(diào)用的C注冊函數(shù)。
static int sub2(lua_State* L)
{
? ? double op1 = luaL_checknumber(L,1);
? ? double op2 = luaL_checknumber(L,2);
? ? lua_pushnumber(L,op1 - op2);
? ? return 1;
}
const char* testfunc = "print(add2(1.0,2.0)) print(sub2(20.1,19))";
int main()
{
? ? lua_State* L = luaL_newstate();
???? luaL_openlibs(L);
? ? //將指定的函數(shù)注冊為Lua的全局函數(shù)變量舅踪,其中第一個字符串參數(shù)為Lua代碼
? ? //在調(diào)用C函數(shù)時使用的全局函數(shù)名纽甘,第二個參數(shù)為實際C函數(shù)的指針。
? ? lua_register(L, "add2", add2);
???? lua_register(L, "sub2", sub2);
? ? //在注冊完所有的C函數(shù)之后硫朦,即可在Lua的代碼塊中使用這些已經(jīng)注冊的C函數(shù)了贷腕。
? ? if (luaL_dostring(L,testfunc))
? ? ? ? printf("Failed to invoke.\n");
? ? lua_close(L);
? ? return 0;
}
2. 在lua語言中調(diào)用C語言生成的.so文件
首先將test.c中的c代碼編譯成.so文件,編譯命令如下:
gcc ?test.c ?-fPIC -shared -o mylibs.so
test.c代碼:
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
//待注冊的C函數(shù)咬展,該函數(shù)的聲明形式在上面的例子中已經(jīng)給出泽裳。
//需要說明的是,該函數(shù)必須以C的形式被導(dǎo)出破婆,因此extern "C"是必須的涮总。
//函數(shù)代碼和上例相同,這里不再贅述祷舀。
int add(lua_State* L)
{
? ? double op1 = luaL_checknumber(L,1);
? ? double op2 = luaL_checknumber(L,2);
? ? lua_pushnumber(L,op1 + op2);
? ? return 1;
}
int sub(lua_State* L)
{
? ? double op1 = luaL_checknumber(L,1);
? ? double op2 = luaL_checknumber(L,2);
? ? lua_pushnumber(L,op1 - op2);
? ? return 1;
}
//luaL_Reg結(jié)構(gòu)體的第一個字段為字符串瀑梗,在注冊時用于通知Lua該函數(shù)的名字烹笔。
//第一個字段為C函數(shù)指針。
//結(jié)構(gòu)體數(shù)組中的最后一個元素的兩個字段均為NULL抛丽,用于提示Lua注冊函數(shù)已經(jīng)到達數(shù)組的末尾谤职。
static luaL_Reg mylibs[] = {
? ? {"add", add},
? ? {"sub", sub},
? ? {NULL, NULL}
};
//該C庫的唯一入口函數(shù)。其函數(shù)簽名等同于上面的注冊函數(shù)亿鲜。見如下幾點說明:
//1. 我們可以將該函數(shù)簡單的理解為模塊的工廠函數(shù)允蜈。
//2. 其函數(shù)名必須為luaopen_xxx,其中xxx表示library名稱蒿柳。Lua代碼require "xxx"需要與之對應(yīng)饶套。
//3. 在luaL_register的調(diào)用中,其第一個字符串參數(shù)為模塊名"xxx"垒探,第二個參數(shù)為待注冊函數(shù)的數(shù)組妓蛮。
//4. 需要強調(diào)的是,所有需要用到"xxx"的代碼圾叼,不論C還是Lua蛤克,都必須保持一致,這是Lua的約定褐奥,
//? 否則將無法調(diào)用咖耘。
int luaopen_mylibs(lua_State* L)
{
? ? luaL_newlib(L,mylibs);
? ? return 1;
}
然后運行test.lua代碼,test.lua文件代碼如下撬码,在shell輸入命令 lua ?test.lua即可
test.lua代碼:
local test = require "mylibs" --指定包名稱
print(test.add(1.0,2.0))
print(test.sub(20.1,19))
print("hello world")
3.參考資料
http://www.voidcn.com/article/p-slqvktkf-bnz.html