Lua与C之间的交互

一、Lua与C之间的交互

1.1 C读写lua全局变量、调用lua函数

代码:
test.lua:

testValue = 10

function add(x, y)
	return x + y + testValue
end

test.c:

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

//调用lua代码中的函数
int lua_add(lua_State *L)
{
        lua_getglobal(L, "add"); //获取add函数

        lua_pushnumber(L, 100);  //向栈中压入第1个参数
        lua_pushnumber(L, 200);  //向栈中压入第2个参数

        if (lua_pcall(L, 2, 1, 0) != 0) //调用lua中的add函数,2个参数,1个返回值
                error(L, "call lua add fail: %s", lua_tostring(L, -1));

        if (!lua_isnumber(L, -1))
                error(L, "function add must return a number.");

        int num = lua_tonumber(L, -1); //获取栈顶元素

        lua_pop(L, 1);  //栈顶元素出栈

        return num;
}

//读lua代码中的全局变量
int lua_get_global(lua_State *L)
{
        lua_getglobal(L, "testValue"); //获取lua中的全局变量testValue,并压入到栈顶

        if (!lua_isnumber(L, -1))
                error(L, "function add must return a number.");

        int num = lua_tonumber(L, -1); //获取栈顶元素

        return num;
}

//写lua代码中的全局变量
void lua_set_global(lua_State *L)
{
        lua_pushnumber(L, 20);         //把值20压入栈顶

        lua_setglobal(L, "testValue"); //lua从栈顶获取值,设置到全局变量testValue中
}

int main()
{
        lua_State *L = luaL_newstate();
        luaL_openlibs(L);

        luaL_dofile(L, "test.lua"); //加载并运行test.lua文件中的代码
        printf("lua add1:%d\n", lua_add(L));
        printf("lua testValue1:%d\n", lua_get_global(L));
        lua_set_global(L);
        printf("lua testValue2:%d\n", lua_get_global(L));
        printf("lua add2:%d\n", lua_add(L));

        lua_close(L);
        return 0;
}

编译:
gcc test.c -o test -I/usr/local/include/luajit-2.0 -llua-5.1

运行结果:

[root@bogon 09]# ./test 
lua add1:310
lua testValue1:10
lua testValue2:20
lua add2:320

1.2 lua调用C函数

1.2.1 C函数作为应用程序的一部分

代码:
test.c

#include "lualib.h"

static int c_add(lua_State *L)
{
        //检查传入的参数是否合法,1表示第1个参数,2表示第2个参数
        int op1 = luaL_checknumber(L, 1);
        int op2 = luaL_checknumber(L, 2);

        int sum = op1 + op2;    //C代码中的运算

        lua_pushnumber(L, sum); //将结果压入栈中,表示返回值

        return 1;               //返回值数量,即压入栈中的返回值个数
}

//字符串作为lua代码
const char* testfunc = "print(add(100, 20))";

int main()
{
        lua_State *L = luaL_newstate();
        luaL_openlibs(L);

        //将C函数c_add注册为lua的全局函数add
        //lua_register(L, "add", c_add); //方式1

        lua_pushcfunction(L, c_add);     //方式2
        lua_setglobal(L, "add");

        if (luaL_dostring(L, testfunc))
                printf("failed to invoke.\n");

        lua_close(L);
        return 0;
}

编译:
gcc test.c -o test -I/usr/local/include/luajit-2.0 -llua-5.1

运行结果:

[root@bogon lua-call-c]# ./test 
120
1.2.2 C函数库成为lua的模块

代码:
test.lua

--package.cpath = "./?.so"

local f = require "mytestlib"

print(f.add(20, 10))
print(f.sub(20, 10))

test.c

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

static int c_add(lua_State *L)
{
        //检查传入的参数是否合法,1表示第1个参数,2表示第2个参数
        int op1 = luaL_checknumber(L, 1);
        int op2 = luaL_checknumber(L, 2);

        int sum = op1 + op2;    //C代码中的运算

        lua_pushnumber(L, sum); //将结果压入栈中,表示返回值

        return 1;               //返回值数量,即压入栈中的返回值个数
}

static int c_sub(lua_State *L)
{
        int op1 = luaL_checknumber(L, 1);
        int op2 = luaL_checknumber(L, 2);

        int sum = op1 - op2;

        lua_pushnumber(L, sum);

        return 1;
}

static const struct luaL_Reg mylib[] = {
        {"add", c_add},
        {"sub", c_sub},
        {NULL, NULL}
};

//根据mytestlib,创建一个table;
//并用数组mylib中的信息填充这个table;
//通过luaL_register注册,将这个table保留到栈中。
int luaopen_mytestlib(lua_State *L)
{
        luaL_register(L, "mytestlib", mylib);
        return 1;
}

编译生成动态库mytestlib.so:
gcc test.c -o mytestlib.o -c -fPIC -I/usr/local/include/luajit-2.0 -llua-5.1
gcc mytestlib.o -shared -o mytestlib.so

运行结果:

[root@bogon 2]# lua test.lua 
30
10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值