闲的蛋疼,让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