首页 > 代码库 > Lua与C的相互调用
Lua与C的相互调用
闲的蛋疼,让C和Lua玩包剪锤。结果C以微弱的优势胜出了。
言归正传,这次主要是想练习Lua和C的相互调用。
一、C调用Lua函数
1. luaL_dofile(L, fn);
该函数可以让Lua虚拟栈读取路径为fn的Lua文件,其实质是:
lua_loadfile(L, fn) || lua_pcall(L, 0, Lua_MUTIRET, 0)
实际上,lua_loadfile只是把Lua文件加载到VM,成为一个可执行的对象,但却还没有执行它,所以还不能使用。
而lua_pcall则把该Lua文件运行了。只有运行了该文件才可以使用其函数。
2. lua_getglobal(L, s)
把全局变量s压入栈顶
3. lua_pushnumber(L, arg)
把参数压入栈顶。
4. lua_pcall(L, nargs, nreturns, errorfunc)
运行栈顶函数,传入参数个数后,虚拟栈会自动pop出相应数量的参数供Lua函数使用。
二、Lua调用C函数
1. 首先要在C中注册C函数到Lua虚拟栈 : lua_register(L, n, f)
可以把名为n的函数f注册到Lua虚拟栈中。其可以分为两步:
lua_pushcfunction(L, f)
lua_setglobal(L, n)
即首先把函数f压入栈顶,再将其pop出来,并设为全局变量。
2. 在lua中调用C函数,直接调用即可
3. 该C函数可以用luaL_checknumber(L, idx)获取栈中序号为idx的参数
4. return 的整型数代表C返回给Lua的返回值个数。 可以先用lua_pushnumber把要返回的值压入栈
关于石头剪刀布的随机,由于没有去维护一个给lua的全局变量随机种子,故每次用C随机了一颗种子给lua,再让lua产生随机数。
另外,本人并没有做错误判断和处理,程序的健壮性尚佳,读者们可以自己思考下哪里需要加上错误判断和处理,加强理解。
代码清单:
1. lua_psr.lua
1 function lua_psr (c_r,seed) 2 math.randomseed(seed); 3 lua_r = math.random(3)-1; 4 c_win,c_draw,c_lose = judge(c_r, lua_r); 5 print_log("the result: c_win = "..c_win.." c_draw = "..c_draw.." c_lose = "..c_lose.."\n"); 6 end
2. testLua.cpp
1 #include <stdio.h> 2 #include <string.h> 3 #include <string> 4 #include <time.h> 5 #include <stdlib.h> 6 extern "C" { 7 #include <lua.h> 8 #include <lauxlib.h> 9 #include <lualib.h> 10 } 11 12 int c_win; 13 int c_lose; 14 int c_draw; 15 16 // called in lua 17 int print_log(lua_State* L) 18 { 19 std::string str = luaL_checkstring(L, 1); 20 printf("%s", str.c_str()); 21 return 0; 22 } 23 24 // called in lua 25 int judge(lua_State *L) 26 { 27 int c = luaL_checknumber(L, 1); 28 int lua = luaL_checknumber(L, 2); 29 if (0 == c - lua) 30 { 31 c_draw++; 32 } 33 else if (-1 == c - lua || 2 == c - lua) 34 { 35 c_lose++; 36 } 37 else 38 { 39 c_win++; 40 } 41 //printf("now the result is : c_win=%d c_draw=%d c_lose=%d ",c_win,c_draw,c_lose); 42 lua_pushnumber(L, c_win); 43 lua_pushnumber(L, c_draw); 44 lua_pushnumber(L, c_lose); 45 return 3; 46 } 47 48 int psr() 49 { 50 int r = rand()%3; 51 return r; 52 } 53 54 void lua_psr(lua_State* L, int r) 55 { 56 lua_getglobal(L, "lua_psr"); 57 lua_pushnumber(L, r); 58 int seed = rand()%100000000; 59 lua_pushnumber(L, seed); 60 lua_pcall(L, 2, 0, 0); 61 } 62 63 int main (void) 64 { 65 srand(time(NULL)); 66 freopen("paper_scissor_rock_c_vs_lua_result.txt", "w", stdout); 67 lua_State *L = luaL_newstate(); 68 luaL_openlibs(L); 69 if (0 != luaL_dofile(L, "lua_psr.lua")) 70 { 71 printf("lua file not found!"); 72 return 0; 73 } 74 lua_register(L, "judge", judge); 75 lua_register(L, "print_log", print_log); 76 printf("now begin! paper scissor rock c vs lua!\n"); 77 for (int i = 0; i < 100; i++) 78 { 79 int r = psr(); 80 lua_psr(L, r); 81 } 82 printf("total turns: %d\n", c_win + c_draw + c_lose); 83 printf("c_win: %d\n", c_win); 84 printf("c_draw: %d\n", c_draw); 85 printf("c_lose: %d\n", c_lose); 86 return 0; 87 }