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

发布于 2024-08-26 19:51:50 字数 797 浏览 4 评论 0原文

我有以下 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 进行包装,根据此 doc,它似乎我应该自动拥有这个函数 new_type_t(2,3) ,但事实并非如此。

如果你包装一个C结构,它也是 映射到 Lua 用户数据。通过添加一个 元表到用户数据,这 提供了一个非常自然的界面。为了 例如,

结构点{ int x,y; };

用法如下:

p=example.new_Point() px=3 py=5 打印(px,py) 3 5

为工会提供类似的访问权限 以及 C++ 类的数据成员。 C 结构是使用创建的 函数 new_Point(),但适用于 C++ 类的创建仅使用 命名 Point()。

I have the follwing C function. How should I wrap it so it can be called from a Lua script?

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

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

I know how to wrapr it if the function parameter type were int or char *. Should I use table type for a C structure?

EDIT: I am using SWIG for the wraping , according to this doc, It seems that I should automatically have this function new_type_t(2,3) , but it is not the case.

If you wrap a C structure, it is also
mapped to a Lua userdata. By adding a
metatable to the userdata, this
provides a very natural interface. For
example,

struct Point{ int x,y; };

is used as follows:

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

Similar access is provided for unions
and the data members of C++ classes. C
structures are created using a
function new_Point(), but for C++
classes are created using just the
name Point().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑看君怀她人 2024-09-02 19:51:50

我匆忙把这些放在一起。它编译了;然后我做了一些最后一刻的编辑。我希望它接近正确的事情。翻遍Lua手册,看看所有不熟悉的函数。

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

const char *metaname = "mine.type_t"; // associated with userdata of type type_t*

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


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

static int lua_lib_a_f_4(lua_State *L) {
  type_t *t = luaL_checkudata(L, 1, metaname);  // check argument type
  lua_pushnumber(L, (lua_Number)lib_a_f_4(t));
  return 1;
}

static int lua_new_t(lua_State *L) { // get Lua to allocate an initialize a 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);
  lua_pop(L, 1);
  return 1;
}

//compile and use it in 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
> 

I put this together in a hurry. It compiled; then I did a few last-minute edits. I hope it's close to the right thing. Go through the Lua manual and look at all the unfamiliar functions.

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

const char *metaname = "mine.type_t"; // associated with userdata of type type_t*

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


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

static int lua_lib_a_f_4(lua_State *L) {
  type_t *t = luaL_checkudata(L, 1, metaname);  // check argument type
  lua_pushnumber(L, (lua_Number)lib_a_f_4(t));
  return 1;
}

static int lua_new_t(lua_State *L) { // get Lua to allocate an initialize a 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);
  lua_pop(L, 1);
  return 1;
}

//compile and use it in 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
> 
dawn曙光 2024-09-02 19:51:50

解决了。

  1. 还应该在 example.i 文件中添加类型定义,仅包含 .h 是不够的。

    %模块示例 
    %{
      #include“liba.h”
    %}
    
    无效 lib_a_f_1(无效);
    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);
    
    结构点{
      整数a;
      整数b;
    };
    
  2. 使用 example.Point() ,而不是 example.new_Point() (SWIG 版本 1.3.35)

     example.Point()
      f=example.Point()
      法=2
      FB=3
      示例.lib_a_f_4(f)
      打印(示例.lib_a_f_4(f))
    

Solved.

  1. Should also add the type definition in the example.i file , just include the .h is not enough.

    %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. use example.Point() ,not example.new_Point() (SWIG Version 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))
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文