Как обернуть функцию C, параметры которой являются указателями на структуры, чтобы ее можно было вызывать из Lua? - PullRequest
2 голосов
/ 26 марта 2010

У меня есть следующая функция 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 *.Должен ли я использовать table тип для структуры C?

РЕДАКТИРОВАТЬ: я использую SWIG для переноса, в соответствии с этим doc , кажется, что я должен автоматически иметь эту функцию new_type_t(2,3), но это не так.

Если вы переносите структуру C, она также сопоставляется с пользовательскими данными Lua.Добавление метатаблицы к данным пользователя обеспечивает очень естественный интерфейс.Например,

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

Ответы [ 2 ]

2 голосов
/ 26 марта 2010

Я спешно собрал это. Составлено; Затем я сделал несколько правок в последнюю минуту. Я надеюсь, что это близко к правильной вещи. Пройдите руководство 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
> 
0 голосов
/ 26 марта 2010

решаемая.

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