2012-07-27 84 views
5

我真的Google了這個問題,但我從來沒有真正得到一個解決方案。lua和C之間共享數組

我想共享C和Lua之間的數組,爲了提高性能,我將避免將數組複製到Lua中。

所以我想傳遞一個從C到Lua的數組的指針。然後從Lua我想直接設置/修改這個數組中的值。


實例C代碼

我想定義我的數組

int mydata[] = {1,2,3,4} 

它集全球到從Lua名爲mydata訪問它。


在Lua中

我想改變這樣

mydata[3] = 9 

的值,並且當我回到C,mydata[3]是9,因爲它是一個指針數組。

這怎麼可能?

+0

由於LUA旨在作爲一個可嵌入的語言用C很好地對接,我期望LUA文檔,以提供充足的例子。你已經瀏覽過這些信息了嗎? – Jens 2012-07-27 13:56:54

+0

感謝您的快速回答。我看過幾乎任何文檔,但我無法找到指向數組的指針示例。 – user1557786 2012-07-27 14:14:35

+0

這是Lua,而不是LUA。這不是一個縮寫;這是一個名字。 – 2012-07-27 19:22:59

回答

19

您可以通過userdata向Lua公開任意數據。如果你給你的用戶數據值metatable,你可以定義這些用戶數據上的各種操作符/操作的行爲。在這種情況下,我們想要向Lua公開一個數組,並在array[index]array[index] = value的情況下定義要執行的操作。

我們通過創建一個足夠容納數組地址的userdata緩衝區來將數組公開給Lua。我們通過使用__index__newindex方法創建了一個metatable來定義索引/分配行爲。

下面是一個完整的工作示例,向Lua公開了一個靜態數組。您的程序可能會有一些其他的呼叫將數組返回給Lua。請注意,根本沒有邊界檢查;如果你嘗試在數組邊界之外索引,你會崩潰。爲了使它更健壯,你需要將userdata改爲具有數組指針和數組大小的結構,這樣你就可以進行邊界檢查。

#include "lauxlib.h" 

// metatable method for handling "array[index]" 
static int array_index (lua_State* L) { 
    int** parray = luaL_checkudata(L, 1, "array"); 
    int index = luaL_checkint(L, 2); 
    lua_pushnumber(L, (*parray)[index-1]); 
    return 1; 
} 

// metatable method for handle "array[index] = value" 
static int array_newindex (lua_State* L) { 
    int** parray = luaL_checkudata(L, 1, "array"); 
    int index = luaL_checkint(L, 2); 
    int value = luaL_checkint(L, 3); 
    (*parray)[index-1] = value; 
    return 0; 
} 

// create a metatable for our array type 
static void create_array_type(lua_State* L) { 
    static const struct luaL_reg array[] = { 
     { "__index", array_index }, 
     { "__newindex", array_newindex }, 
     NULL, NULL 
    }; 
    luaL_newmetatable(L, "array"); 
    luaL_openlib(L, NULL, array, 0); 
} 

// expose an array to lua, by storing it in a userdata with the array metatable 
static int expose_array(lua_State* L, int array[]) { 
    int** parray = lua_newuserdata(L, sizeof(int**)); 
    *parray = array; 
    luaL_getmetatable(L, "array"); 
    lua_setmetatable(L, -2); 
    return 1; 
} 

// test data 
int mydata[] = { 1, 2, 3, 4 }; 

// test routine which exposes our test array to Lua 
static int getarray (lua_State* L) { 
    return expose_array(L, mydata); 
} 

int __declspec(dllexport) __cdecl luaopen_array (lua_State* L) { 
    create_array_type(L); 

    // make our test routine available to Lua 
    lua_register(L, "array", getarray); 
    return 0; 
} 

用法:

require 'array' 

foo = array() 
print(foo) -- userdata 

-- initial values set in C 
print(foo[1]) 
print(foo[2]) 
print(foo[3]) 
print(foo[4]) 

-- change some values 
foo[1] = 2112 
foo[2] = 5150 
foo[4] = 777 

-- see changes 
print(foo[1]) 
print(foo[2]) 
print(foo[3]) 
print(foo[4]) 
+0

哇,我不能感謝你爲這個傑出的職位工作的例子。這是我正在尋找的,所以再次感謝! 我是這個論壇的新手,我該如何給你點分數? – user1557786 2012-07-27 18:22:42

+1

對於初學者來說,像我一樣,我真的很感謝luabind的易用性 - 對於您的簡單問題,您會發現需要很多代碼才能直接在lua中執行 - 使用luabind,基本上是一個班輪 - 您應該檢查它這裏有一個很棒的介紹http://blog.nuclex-games.com/tutorials/cxx/luabind-introduction/ - 當你對事物感到更加舒適後,在lua中直接開發仍然更好 - 但是對於luabind,你基本上可以做很多事情都非常快以獲得工作理念 – Steve 2012-07-28 12:58:15