lua52 C API测试代码
生活随笔
收集整理的這篇文章主要介紹了
lua52 C API测试代码
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
//這是一篇lua與C++交互的情景測試 #include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>
#include <string.h>
#include <limits.h>#pragma region not_importent_
static void stackDump (lua_State *L)
{int i;int top = lua_gettop(L);for(i=1;i<=top;i++){/*repeatforeachlevel*/int t = lua_type(L, i);switch (t) {case LUA_TSTRING:/* strings */printf("`%s'", lua_tostring(L, i));break;case LUA_TBOOLEAN:/* booleans */printf(lua_toboolean(L, i) ? "true" : "false");break;case LUA_TNUMBER:/* numbers */printf("%g", lua_tonumber(L, i));break;default:/* other values */printf("%s", lua_typename(L, t));break;}printf(" ");/* put a separator */}printf("\n");/* end the listing */
}void error (lua_State *L, const char *fmt, const char *str) {printf(fmt, str);
}
//待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;
}
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;
}
#pragma endregion//
void test_c_call_lua_fun_noParam()
{const char* buff = "print(\"hello\")";int err;//initlua_State* L = luaL_newstate();luaL_openlibs(L);//load bufferr = luaL_loadbuffer(L,buff,strlen(buff),"line") ;err += lua_pcall(L,0,0,0);int s = lua_gettop(L);if(err){fprintf(stderr,"%s",lua_tostring(L,-1));lua_pop(L,1);}//close
lua_close(L);}
//
void test_c_call_lua_fun_withParam()
{lua_State *L = luaL_newstate();luaL_openlibs(L);if (luaL_loadfile(L, "luafile2.lua") || lua_pcall(L, 0, 0, 0)){error(L, "cannot run configuration file: %s",lua_tostring(L, -1));return;}lua_getglobal(L, "do_lua_kk");lua_getglobal(L, "a");lua_getglobal(L, "do_lua_error");lua_getglobal(L, "b");lua_getglobal(L, "do_c_one");lua_getglobal(L, "do_c");lua_getglobal(L, "width");lua_getglobal(L, "height");// lua_getglobal(L, "do_c_two");stackDump(L); //打印結(jié)果:function `lua_str_a' function `lua_str_b' function function 999 300int k = 100;k = lua_pcall(L, 2, 1, 1);stackDump(L); //打印結(jié)果:function `lua_str_a' function `lua_str_b' function 8888 /*lua 執(zhí)行棧上最上面的函數(shù),使用棧上2個參數(shù),向棧壓入3個返回值使用棧上第1位置的函數(shù)do_lua_kk作為錯誤處理回調(diào)函數(shù),輸出:-------->do_c999--add--300-->--2222*/k = lua_pcall(L, 1, 0, 0);stackDump(L); lua_close(L);
}
//
void test_c_call_lua_fun_withParam2()
{lua_State* L = luaL_newstate();//luaL_dostring 等同于luaL_loadstring() || lua_pcall()//注意:在能夠調(diào)用Lua函數(shù)之前必須執(zhí)行Lua腳本,否則在后面實際調(diào)用Lua函數(shù)時會報錯,//錯誤信息為:"attempt to call a nil value."const char* lua_function_code = "function add(x,y) return x + y end";if (luaL_dostring(L,lua_function_code)) {printf("Failed to run lua code.\n");return;}double x = 1.0, y = 2.3;lua_getglobal(L,"add");lua_pushnumber(L,x);lua_pushnumber(L,y);//下面的第二個參數(shù)表示帶調(diào)用的lua函數(shù)存在兩個參數(shù)。//第三個參數(shù)表示即使帶調(diào)用的函數(shù)存在多個返回值,那么也只有一個在執(zhí)行后會被壓入棧中。//lua_pcall調(diào)用后,虛擬棧中的函數(shù)參數(shù)和函數(shù)名均被彈出。if (lua_pcall(L,2,1,0)) {printf("error is %s.\n",lua_tostring(L,-1));return;}//此時結(jié)果已經(jīng)被壓入棧中。if (!lua_isnumber(L,-1)) {printf("function 'add' must return a number.\n");return;}double ret = lua_tonumber(L,-1);lua_pop(L,-1); //彈出返回值。printf("The result of call function is %f.\n",ret);lua_close(L);}
//
void test_c_use_lua_variant()
{const char* luascript = "width=111 ; height=222";lua_State* L = luaL_newstate();int w,h;//luaL_loadfile的作用是編譯lua文件為一個chunk//把這個chunk當(dāng)作一個匿名函數(shù)壓在棧上//lua_pcall的作用是執(zhí)行這個匿名函數(shù),然后才能取得棧上的值if(luaL_loadstring(L,luascript) || lua_pcall(L,0,0,0)){printf("Error msg is %s.\n",lua_tostring(L,-1));return;}lua_getglobal(L,"width"); //調(diào)用次函數(shù),則把全局變量壓棧lua_getglobal(L,"height");//這里壓棧次序決定了后面取值的索引if(!lua_isnumber(L,-2)){printf("width must be number\n");return;}if(!lua_isnumber(L,-1)){printf("height must be number\n");return ;}w = lua_tointeger(L,-2);h = lua_tointeger(L,-1);printf("width = %d height = %d\n",w,h);lua_close(L);
}
//
void test_c_use_lua_table()
{lua_State* L = luaL_newstate();if (luaL_loadstring(L,"background = { r = 0.30, g = 0.10, b = 0 }") || lua_pcall(L,0,0,0)) {printf("Error Msg is %s.\n",lua_tostring(L,-1));return;}lua_getglobal(L,"background");if (!lua_istable(L,-1)) {printf("'background' is not a table.\n" );return;}//下面取棧上的table內(nèi)容lua_getfield(L,-1,"r");if (!lua_isnumber(L,-1)) {printf("Invalid component in background color.\n");return;}int r = (int)(lua_tonumber(L,-1) * 255);lua_pop(L,1);//出棧
lua_getfield(L,-1,"g");if (!lua_isnumber(L,-1)) {printf("Invalid component in background color.\n");return;}int g = (int)(lua_tonumber(L,-1) * 255);lua_pop(L,1);lua_pushnumber(L,0.4);//入棧,棧頂位置-1的值是0.4lua_setfield(L,-2,"b");//設(shè)置background["b"]=0.4,注意-2這個位置表示table的位置!!lua_getfield(L,-1,"b");//取table值
stackDump(L);if (!lua_isnumber(L,-1)) {printf("Invalid component in background color.\n");return;}int b = (int)(lua_tonumber(L,-1) * 255);printf("r = %d, g = %d, b = %d\n",r,g,b);lua_pop(L,1);stackDump(L);lua_pop(L,1); //棧被清空了
lua_close(L);
}
//
void test_c_new_lua_table()
{lua_State* L = luaL_newstate();lua_newtable(L);//Lua會生成一個新的table對象并將其壓入棧中。lua_pushnumber(L,0.3);stackDump(L);//table 0.3lua_setfield(L,-2,"r");//設(shè)置table["r"]=0.3完了把0.3彈出stackDump(L);//table
lua_pushnumber(L,0.1);lua_setfield(L,-2,"g");lua_pushnumber(L,0.4);lua_setfield(L,-2,"b");stackDump(L);//tablelua_setglobal(L,"background");//棧頂元素出棧stackDump(L);//nil//調(diào)用該宏后,Lua會將當(dāng)前棧頂?shù)闹蒂x值給第二個參數(shù)指定的全局變量名。//該宏在執(zhí)行成功后,會將剛剛賦值的值從棧頂彈出。
lua_getglobal(L,"background");//把background壓棧stackDump(L);//tableif (!lua_istable(L,-1)) {printf("'background' is not a table.\n" );return;}lua_getfield(L,-1,"r");//table["r"]壓棧stackDump(L);//table 0.3if (!lua_isnumber(L,-1)) {printf("Invalid component in background color.\n");return;}int r = (int)(lua_tonumber(L,-1) * 255);lua_pop(L,1);//table
lua_getfield(L,-1,"g");//table 0.1if (!lua_isnumber(L,-1)) {printf("Invalid component in background color.\n");return;}int g = (int)(lua_tonumber(L,-1) * 255);lua_pop(L,1);//table
lua_getfield(L,-1,"b");//table 0.4if (!lua_isnumber(L,-1)) {printf("Invalid component in background color.\n");return;}int b = (int)(lua_tonumber(L,-1) * 255);printf("r = %d, g = %d, b = %d\n",r,g,b);lua_pop(L,1);//tablelua_pop(L,1);//nil
lua_close(L);
}
//
void test_lua_call_c_fun()
{const char* testfunc = "print(add2(1.0,2.0)) print(sub2(20.1,19))";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);
}
//
//lua文件里的print被C調(diào)用時,是可以打印到終端的!!!
void test_lua_call_c_dll_fun()
{lua_State* L = luaL_newstate();luaL_openlibs(L);if(luaL_dofile(L,"lua_call_c.lua"))printf("load lua_call_c.lua failed\n");;lua_close(L);
}#define BITS_PER_WORD (CHAR_BIT * sizeof(int))
#define I_WORD(i) ((unsigned int)(i))/BITS_PER_WORD
#define I_BIT(i) (1 << ((unsigned int)(i)%BITS_PER_WORD))typedef struct NumArray {int size;unsigned int values[1];
} NumArray;extern "C" int newArray(lua_State* L)
{//1. 檢查第一個參數(shù)是否為整型。以及該參數(shù)的值是否大于等于1.int n = luaL_checkint(L,1);luaL_argcheck(L, n >= 1, 1, "invalid size.");size_t nbytes = sizeof(NumArray) + I_WORD(n - 1) * sizeof(int);//2. 參數(shù)表示Lua為userdata分配的字節(jié)數(shù)。同時將分配后的userdata對象壓入棧中。NumArray* a = (NumArray*)lua_newuserdata(L,nbytes);a->size = n;for (int i = 0; i < I_WORD(n - 1); ++i)a->values[i] = 0;//獲取注冊表變量myarray,該key的值為metatable。luaL_getmetatable(L,"myarray");//將userdata的元表設(shè)置為和myarray關(guān)聯(lián)的table。同時將棧頂元素彈出。lua_setmetatable(L,-2);return 1;
}extern "C" int setArray(lua_State* L)
{//1. Lua傳給該函數(shù)的第一個參數(shù)必須是userdata,該對象的元表也必須是注冊表中和myarray關(guān)聯(lián)的table。//否則該函數(shù)報錯并終止程序。NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");int index = luaL_checkint(L,2) - 1;//2. 由于任何類型的數(shù)據(jù)都可以成為布爾值,因此這里使用any只是為了確保有3個參數(shù)。luaL_checkany(L,3);luaL_argcheck(L,a != NULL,1,"'array' expected.");luaL_argcheck(L,0 <= index && index < a->size,2,"index out of range.");if (lua_toboolean(L,3))a->values[I_WORD(index)] |= I_BIT(index);elsea->values[I_WORD(index)] &= ~I_BIT(index);return 0;
}extern "C" int getArray(lua_State* L)
{NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");int index = luaL_checkint(L,2) - 1;luaL_argcheck(L, a != NULL, 1, "'array' expected.");luaL_argcheck(L, 0 <= index && index < a->size,2,"index out of range");lua_pushboolean(L,a->values[I_WORD(index)] & I_BIT(index));return 1;
}extern "C" int getSize(lua_State* L)
{NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");luaL_argcheck(L,a != NULL,1,"'array' expected.");lua_pushinteger(L,a->size);return 1;
}extern "C" int array2string(lua_State* L)
{NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");lua_pushfstring(L,"array(%d)",a->size);return 1;
}static luaL_Reg arraylib_f [] = { {"new", newArray},{NULL, NULL}
}; static luaL_Reg arraylib_m [] = {{"set", setArray},{"get", getArray},{"size", getSize},{"__tostring", array2string}, //print(a)時Lua會調(diào)用該元方法。
{NULL, NULL}
};int luaopen_testuserdata(lua_State* L)
{//1. 創(chuàng)建元表,并將該元表指定給newArray函數(shù)新創(chuàng)建的userdata。在Lua中userdata也是以table的身份表現(xiàn)的。//這樣在調(diào)用對象函數(shù)時,可以通過驗證其metatable的名稱來確定參數(shù)userdata是否合法。luaL_newmetatable(L,"myarray");lua_pushvalue(L,-1);//2. 為了實現(xiàn)面對對象的調(diào)用方式,需要將元表的__index字段指向自身,同時再將arraylib_m數(shù)組中的函數(shù)注冊到//元表中,之后基于這些注冊函數(shù)的調(diào)用就可以以面向?qū)ο蟮男问秸{(diào)用了。//lua_setfield在執(zhí)行后會將棧頂?shù)膖able彈出。lua_setfield(L,-2,"__index");//將這些成員函數(shù)注冊給元表,以保證Lua在尋找方法時可以定位。NULL參數(shù)表示將用棧頂?shù)膖able代替第二個參數(shù)。
luaL_newlib(L,arraylib_m);//這里只注冊的工廠方法。
luaL_newlib(L,arraylib_f);return 1;
}
int main()
{test_c_call_lua_fun_noParam();test_c_call_lua_fun_withParam();test_c_call_lua_fun_withParam2();test_c_use_lua_variant();test_c_use_lua_table();test_c_new_lua_table();test_lua_call_c_fun();test_lua_call_c_dll_fun();getchar();return 0;
}
轉(zhuǎn)載于:https://www.cnblogs.com/jwk000/p/3572250.html
總結(jié)
以上是生活随笔為你收集整理的lua52 C API测试代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 2553 N皇后问题 搜索
- 下一篇: FreeSql (二十四)Linq To