2010-03-26 10 views
2

J'ai la fonction C suivante. Comment dois-je l'emballer pour qu'il puisse être appelé à partir d'un script Lua?Comment faire pour enchaîner une fonction C dont les paramètres sont pointeur vers des structures, afin qu'elle puisse être appelée depuis Lua?

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

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

Je sais comment wrapr si le type de paramètre de fonction étaient int ou char *. Devrais-je utiliser le type table pour une structure en C?

EDIT: J'utilise SWIG pour le wrapping, selon ce doc, il semble que je devrais avoir automatiquement cette fonction new_type_t(2,3), mais ce n'est pas le cas.

Si vous enroulez une structure C, il est également mappé à une Lua userdata. En ajoutant un metatable aux données d'utilisateur, ce fournit une interface très naturelle. Pour exemple,

struct Point{ int x,y; };

est utilisé comme suit:

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

accès similaire est prévu pour les syndicats et les membres de données des classes C++. Les structures C sont créées à l'aide d'une fonction new_Point(), mais pour C++ , les classes sont créées en utilisant uniquement le point Point().

+0

Évitez SWIG. Il crée au moins autant de problèmes que cela provoque, et il est assez facile de créer les appels d'API à la main. –

+0

@Norman: J'ai besoin d'emballer beaucoup d'API existantes pour que je puisse l'appeler à partir de lua, donc une manière automaic est un MUST. Avez-vous d'autres recommandations? – pierrotlefou

+0

Combien coûte "lots"? Si c'est moins de 100 fonctions, vous feriez mieux de le faire à la main. Mais si vous voulez essayer une méthode automatisée, 'tolua' est légèrement moins fou que SWIG. Seulement un peu. Même «tolua» ajoute beaucoup de poids inutile. http://www.tecgraf.puc-rio.br/~celes/tolua/ –

Répondre

2

Je mets cela ensemble rapidement. Il a compilé; Puis j'ai fait quelques modifications de dernière minute. J'espère que c'est proche de la bonne chose. Passez en revue le manuel de Lua et regardez toutes les fonctions qui ne vous sont pas familières.

#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 
[email protected]:/opt/task/dt/lua/try1# gcc -shared -o mylib.so -I/usr/include/lua5.1/ -llua *.c -ldl 
[email protected]:/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

Merci. Mais comment dois-je appeler cette fuction dans le script Iua? – pierrotlefou

+0

Vous compilez cette fonction dans la bibliothèque partagée 'mylib.so', puis' require' pour obtenir un nouveau module 'mylib'. Découvrez * Programmation en Lua * (http: //www.lua.org/pil2) ou la 1ère édition gratuite. –

0

Résolu.

  1. faut ajouter aussi la définition de type dans le fichier example.i, il suffit d'inclure le .h ne suffit pas.

    %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. utilisation example.Point(), non 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))