如何包装一个参数为指向结构体指针的 C 函数,以便它可以从 Lua 中调用?

我有以下的C函数。我应该如何包装它,以便可以从Lua脚本中调用?

typedef struct tagT{
    int a ;
    int b ;
} type_t;

int lib_a_f_4(type_t *t)
{
     return t->a * t->b ;
}

如果函数参数类型是int或char*,我知道如何包装它。那么对于C结构体,我应该使用table类型吗?

编辑:我使用SWIG进行包装,根据这个文档,似乎我应该自动拥有这个函数new_type_t(2,3),但实际上并不是这样。

如果您包装了一个C结构体,它也会映射到Lua userdata。通过向userdata添加元表,这提供了一种非常自然的接口。例如,

struct Point{ int x,y; };

用法如下:

p=example.new_Point() p.x=3 p.y=5 print(p.x,p.y) 3 5

类似的访问还提供给联合和C++类的数据成员。 C结构使用函数new_Point()创建,但C++类只需使用名称Point()即可创建。

原文链接 https://stackoverflow.com/questions/2521244

点赞
stackoverflow用户41661
stackoverflow用户41661
#include <lua.h>
#include <lauxlib.h>

const char *metaname = "mine.type_t"; //与userdata类型type_t*相关联的名称

typedef struct tagT{
    int a ;
    int b ;
}type_t;

int lib_a_f_4(type_t *t) //计算 type_t的a和 b的乘积
{
    return t->a * t->b ;
}

static int lua_lib_a_f_4(lua_State *L) { 
    //检查类型并调用 lib_a_f_4 计算返回值
    type_t *t = luaL_checkudata(L, 1, metaname);  //检查参数类型
    lua_pushnumber(L, (lua_Number)lib_a_f_4(t));  //将函数返回值入栈
    return 1;
}

static int lua_new_t(lua_State *L) { //让Lua分配并初始化type_t*内存
    int a = luaL_checkint(L, 1);
    int b = luaL_checkint(L, 2);
    type_t *t = lua_newuserdata(L, sizeof(*t));
    luaL_getmetatable(L, metaname);
    lua_setmetatable(L, -2);
    t->a = a;
    t->b = b;
    return 1;
}

static const struct luaL_reg functions[] = { //注册函数
    { "lib_a_f_4", lua_lib_a_f_4 },
    { "new_t", lua_new_t },
    { NULL, NULL }
};

int mylib_open(lua_State *L) {
    luaL_register(L, "mylib", functions);
    luaL_newmetatable(L, metaname); //创建 metatable 并将其推到栈上
    lua_pop(L, 1);
    return 1;
}

//编译并在lua中使用
root@pierr-desktop:/opt/task/dt/lua/try1# gcc -shared -o mylib.so -I/usr/include/lua5.1/ -llua *.c -ldl
root@pierr-desktop:/opt/task/dt/lua/try1# lua
Lua 5.1.3  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require("mylib")
> t=mylib.new_t(2,3)
> mylib.lib_a_f_4(t)
> print(mylib.lib_a_f_4(t))
6
>
2010-03-26 05:59:36
stackoverflow用户115722
stackoverflow用户115722
  1. example.i 文件中还应该添加类型定义,仅包含 .h 是不够的。

    %module example
    %{
      #include "liba.h"
    %}
    
    void lib_a_f_1(void);
    int  lib_a_f_2(int a, int b);
    int lib_a_f_3(const char *s);
    int lib_a_f_4(struct Point *t);
    
    struct Point{
      int a;
      int b;
    };
    
  2. 使用 example.Point(),而不是 example.new_Point() (SWIG 版本 1.3.35)

      example.Point()
      f=example.Point()
      f.a=2
      f.b=3
      example.lib_a_f_4(f)
      print(example.lib_a_f_4(f))
    
2010-03-26 10:34:25