Ubuntu Lua调用C函数。

      用了很久lua,框架原因,今天写一下lua调用so库。

      真的是不做不知道,一做真奇妙。网上那么多篇文章,基本上都是你抄我,我抄你。错误都一样,验证都没验证过。。。

      先声明一下我的环境,Ubuntu 18.04,lua5.3

1.概念补充,lua和c交互是通过一个虚拟的栈来交互的,为什么是这样?

C与Lua之间通信关键内容在于一个虚拟的栈。几乎所有的调用都是对栈上的值进行操作,所有C与Lua之间的数据交换也都通过这个栈来完成。另外,也可以使用栈来保存临时变量。每一个与Lua通信的C函数都有其独有的虚拟栈,虚拟栈由Lua管理。
栈的使用解决了C和Lua之间两个不协调的问题:第一,Lua会自动进行垃圾收集,而C要求显式的分配存储单元,两者引起的矛盾。第二,Lua中的动态类型和C中的静态类型不一致引起的混乱。

2.要想调用C中的方法,则需要把C编译成动态库,我是在linux下,所以是.so,代码如下

c_so.cpp

extern "C" {
  #include <stdio.h>
  #include <lua.h>
  #include <lualib.h>
  #include <lauxlib.h>
}
 
 
//自定义函数
static int my_add(lua_State *L)
{
    int x = lua_tonumber(L,1); //第一个参数,转换为数字
    int y = lua_tonumber(L,2); //第二个参数,转换为数字
    int sum = x + y;           
    lua_pushnumber(L, sum);    //将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
    return 1; //返回sum计算结果
}
 
static int showstr(lua_State *L)
{
   //从lua中传入的第一个参数
   const char *str = lua_tostring (L, 1);
 
   printf ("c program str = %s\n", str);
   return 0;
}
 
/* 需要一个"luaL_Reg"类型的结构体,其中每一个元素对应一个提供给Lua的函数。
 * 每一个元素中包含此函数在Lua中的名字,以及该函数在C库中的函数指针。
 * 最后一个元素为“哨兵元素”(两个"NULL"),用于告诉Lua没有其他的函数需要注册。
 */
static luaL_Reg funclist[] =
{
    {"add", my_add}, //my_add()函数,lua中访问时使用名称为add
    {"show", showstr}, //showstr()函数,lua中访问时使用名称为show
    {NULL, NULL},  //最后必须有这个
};
 
/* 此函数为C库中的“特殊函数”。
 * 通过调用它注册所有C库中的函数,并将它们存储在适当的位置。
 * 此函数的命名规则应遵循:
 * 1、使用"luaopen_"作为前缀。
 * 2、前缀之后的名字将作为"require"的参数。
 */
extern "C" int luaopen_mylib(lua_State *L )
{
     /* void luaL_newlib (lua_State *L, const luaL_Reg l[]);
     * 创建一个新的"table",并将"l"中所列出的函数注册为"table"的域。
     */ 
    luaL_newlib(L, funclist);
    return 1;
}

然后编译 gcc -shared -fPIC c_so.cpp -o mylib.so -I /home/lk/my_skynet_learning/skynet/3rd/lua/

编译完成后将会得到mylib.so

testso.lua

local mylib = require "mylib"

local i = mylib.add(1, 2)
print(i)

local j = mylib.show('真的太多坑了')

运行结果如下

网上搜的真的是各种坑。哎。

猜你喜欢

转载自blog.csdn.net/banfushen007/article/details/108984748