ホームページ  >  記事  >  バックエンド開発  >  Lua と C 言語は相互に呼び出します

Lua と C 言語は相互に呼び出します

WBOY
WBOYオリジナル
2016-08-08 09:23:391900ブラウズ

lua と C 言語の間の多くの相互変調が lua-nginx-module に表示されます。ここでは、「Lua プログラミング」の第 24 章から第 27 章にあるテスト コードをいくつか紹介します。

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdarg.h>
#include <stdlib.h>

#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

コンパイル: gcc test.c -I/usr/local/include/luajit-2.0 -llua-5.1 -lm

以上、LuaとC言語の相互呼び出しについて内容も含めて紹介しましたが、PHPチュートリアルに興味のある方の参考になれば幸いです。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。