lua和c语言之间的互调大量出现在lua-nginx-module中,这里给出《lua程序设计》第24-27章的一些测试代码。
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_COLOR 255
static void stackDump(lua_State *L);
static int l_split(lua_State *L)
{
const char *s = luaL_checkstring(L, 1);
const char *sep = luaL_checkstring(L, 2);
const char *e;
int i = 1;
lua_newtable(L);
while ((e = strchr(s, *sep)) != NULL)
{
lua_pushlstring(L, s, e-s);
lua_rawseti(L, -2, i ++);
s = e + 1;
}
lua_pushstring(L, s);
lua_rawseti(L, -2, i);
return 1;
}
int l_map(lua_State *L)
{
int i, n;
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TFUNCTION);
n = lua_objlen(L, 1);
for (i = 1; i <= n; i ++)
{
//stackDump(L);
//printf("=====1=====\n");
lua_pushvalue(L, 2);
//stackDump(L);
//printf("=====2=====\n");
lua_rawgeti(L, 1, i);
//stackDump(L);
//printf("=====3=====\n");
lua_call(L, 1, 1);
//stackDump(L);
//printf("=====4=====\n");
lua_rawseti(L, 1, i);
//stackDump(L);
//printf("=====5=====\n");
}
return 0;
}
// 通过Lua调用的c函数,通过打印栈说明每个函数有独立的栈
// 将c函数注册到lua中,从而被lua调用。
static int l_sin(lua_State *L)
{
double d = lua_tonumber(L, 1);
lua_pushnumber(L, sin(d));
// stackDump(L);
// printf("====l_sin===\n");
return 1;
}
// c 调用lua 函数
// 从Lua中得到函数,在c语言中传入参数。
double f(lua_State *L,double x, double y)
{
double z;
lua_getglobal(L, "f");
lua_pushnumber(L, x);
lua_pushnumber(L, y);
// table function 1.1 2.2 说明c语言调用Lua会共享相同的栈.
// stackDump(L);
// printf("=====f=====\n");
if (lua_pcall(L, 2, 1, 0) != 0)
printf("call f error\n");
if (!lua_isnumber(L, -1))
printf("function f must return a number\n");
z = lua_tonumber(L, -1);
lua_pop(L, 1);
return z;
}
int getfield(lua_State *L, const char *key)
{
int result;
// stackDump(L);
// printf("==1==\n");
lua_getfield(L, -1, key);
// stackDump(L);
// printf("==2==\n");
if (!lua_isnumber(L, -1))
printf("invalid component\n");
result = lua_tonumber(L, -1);
lua_pop(L, 1);
// stackDump(L);
// printf("==4==\n");
return result;
}
static void stackDump(lua_State *L)
{
int i;
int top = lua_gettop(L);
for (i = 1; i <= top; ++ i)
{
int t = lua_type(L, i);
switch(t) {
case LUA_TSTRING:
printf("'%s'", lua_tostring(L, i));
break;
case LUA_TBOOLEAN:
printf(lua_toboolean(L, i) ? "true" : "false");
break;
case LUA_TNUMBER:
printf("%g", lua_tonumber(L, i));
break;
default:
printf("%s", lua_typename(L, t));
break;
}
printf(" ");
}
printf("\n");
}
void load(lua_State *L, const char *fname, int *w, int *h) {
if (luaL_loadfile(L, fname) || lua_pcall(L, 0, 0, 0))
printf("cannot run config.file\n");
/*lua_getglobal(L, "height");
lua_getglobal(L, "width");
if (!lua_isnumber(L, -2))
printf("width should be a number\n");
if (!lua_isnumber(L, -1))
printf("height should be a number\n");
*w = lua_tointeger(L, -2);
*h = lua_tointeger(L, -1);*/
lua_getglobal(L, "table");
if (!lua_istable(L, -1))
printf("background should be table\n");
printf("%f\n", f(L, 1.1, 2.2));
float red = getfield(L, "r");
float green = getfield(L, "g");
float blue = getfield(L, "b");
printf("%f, %f, %f\n", red, green, blue);
}
// lua 调用c代码可以模仿这里的格式
const char* testfunc = "t = mysplit(\"hi, hello\", \",\"); print(t[1], t[2])";
int main(void)
{
char buff[256];
int error;
lua_State *L = luaL_newstate();
luaL_openlibs(L);
int w, h;
// load(L, "test.lua", &w, &h);
lua_pushcfunction(L, l_sin);
lua_setglobal(L, "mysin");
lua_pushcfunction(L, l_map);
lua_setglobal(L, "mymap");
lua_pushcfunction(L, l_split);
lua_setglobal(L, "mysplit");
if (luaL_dostring(L, testfunc))
fprintf(stderr, "%s", lua_tostring(L, -1));
/*
while (fgets(buff, sizeof(buff), stdin) != NULL)
{
error = luaL_loadbuffer(L, buff, strlen(buff), "line");
stackDump(L);
error = error || lua_pcall(L, 0, 0, 0);
stackDump(L);
}
if (error) {
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}*/
lua_close(L);
return 0;
}
test.lua
BULE = {r = 0, g = 0, b = 1}
table = {["r"] = 10, ["g"] = 23, ["b"] = 33}
function f(x, y)
return x + y
end