2010-03-26 50 views
2

我有以下的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 ; 
} 

我知道如何wrapr,如果函數參數類型爲intchar *。我應該使用table類型爲C結構嗎?

編輯:我使用SWIG的包裝,根據這doc,似乎我應該自動具有此功能new_type_t(2,3),但事實並非如此。

如果你打包一個C結構,它也是 映射到一個Lua用戶數據。通過添加一個 metatable到用戶數據,這個 提供了一個非常自然的接口。對於 例如,

struct Point{ int x,y; };

的使用如下:

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

類似的訪問提供了一種用於工會 和C++類的數據成員。 C 使用 函數new_Point()創建結構,但對於C++ 類僅使用 名稱Point()創建。

+0

避免痛飲。它造成的問題至少與其造成的問題一樣多,並且手工創建API調用很容易。 – 2010-03-26 17:57:12

+0

@Norman:我需要包裝大量的遺留API,以便我可以從lua調用它,所以自動方式是必須的。你有其他建議嗎? – pierrotlefou 2010-03-29 01:59:24

+0

「多少」是多少?如果它少於100個功能,那麼最好是手動完成。但是如果你想嘗試一種自動化的方法,'tolua'比SWIG稍微不瘋狂。只是輕微。即使'tolua'也增加了很多不必要的重量。 http://www.tecgraf.puc-rio.br/~celes/tolua/ – 2010-03-29 02:02:15

回答

2

我把它放在一起匆忙。它彙編;然後我做了一些最後一刻的編輯。我希望這是接近正確的事情。閱讀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 
[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

謝謝。但我應該如何在lua腳本中調用這個功能? – pierrotlefou 2010-03-26 06:30:21

+0

您可以將此函數編譯爲共享庫mylib.so,然後'require'獲得一個新模塊'mylib'。退房*在Lua編程*(http://www.lua。org/pil2)或免費的第一版。 – 2010-03-26 17:59:41

0

已解決。

  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()(痛飲版本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)) 
    
相關問題