首页 > 代码库 > 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
Lua_psr.lua

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 }
testLua.cpp