Lua 和 C 语言相互调用

2019-09-22 language lua

Lua 是扩展性非常良好的语言,虽然核心非常精简,但是用户可以依靠 Lua 库来实现大部分工作,还可以通过与 C 函数相互调用来扩展程序功能。

在 C 中嵌入 Lua 脚本既可以让用户在不重新编译代码的情况下修改 Lua 代码更新程序,也可以给用户提供一个自由定制的接口,这种方法遵循了机制与策略分离的原则;在 Lua 中调用 C 函数可以提高程序的运行效率。

Lua 与 C 的相互调用在工程中相当实用,这里就简单讲解 Lua 与 C 相互调用的方法。

简介

使用时需要安装 liblua5.4-dev 开发库。

调用脚本

其中存在一个加法的 Lua 脚本。

function Add(x,y)
    return x + y
end

对应的 C 调用实现如下。

#include <stdio.h>

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

int main(void)
{
	int sum;
	lua_State *lua;

	lua = luaL_newstate();
	luaL_openlibs(lua);
	luaL_dofile(lua, "add.lua");

	lua_getglobal(lua, "Add");
	lua_pushnumber(lua, 1);
	lua_pushnumber(lua, 2);
	lua_call(lua, 2, 1); // two argument and one return value
	sum = (int)lua_tonumber(lua, -1);
	lua_pop(lua, 1);
	printf("the sum is %d\n", sum);

	lua_close(lua);
	return 0;
}

其中关键的就是栈,所有的参数和返回值都是通过栈进行处理。

脚本调用

通过 Lua 调用 C 语言有几种方式:A) 在 C 语言中注册函数;B) 生成动态库,在脚本中通过 require 调用。

如下直接加载字符串脚本。

#include <stdio.h>
#include <string.h>

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

static int Hello(lua_State *lua)
{
	char buff[128];
	snprintf(buff, sizeof(buff), "Hello %s!!!", luaL_checkstring(lua, 1));
	lua_pushstring(lua, buff);
	return 1;
}

int main(void)
{
	lua_State *lua = luaL_newstate();
	luaL_openlibs(lua);
	lua_register(lua, "Hello", Hello);

	if (luaL_dostring(lua, "print(Hello('World'))"))
		printf("failed to invoke.\n");
	lua_close(lua);
	return 0;
}

下面代码则是生成动态库。

#include <math.h>

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

static int simple_sin(lua_State *lua)
{   
	double d = luaL_checknumber(lua, 1);
	lua_pushnumber(lua, sin(d));
	return 1;  // number of results
}

static const struct luaL_Reg libs[] = {
	{"msin", simple_sin},
	{NULL, NULL}
};

extern int luaopen_hey(lua_State* lua)
{
	luaL_newlib(lua, libs);
	return 1;
}

然后脚本中可以通过如下方式调用。

local hey = require "hey"
print(hey.msin(3.14 / 2))