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))