2012-07-27 83 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