在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,因为它是数组的指针。这可能吗?

点赞
用户501459
用户501459

您可以通过“userdata”向Lua公开任意数据。如果给您的userdata值添加“metatable”,则可以为这些userdata定义各种运算符/操作的行为。在这种情况下,我们想向Lua公开一个数组,并定义在“array[index]”和“array[index] = value”情况下要做什么。

我们通过创建足够大的userdata缓冲区来向Lua公开数组以保存数组的地址。我们通过创建具有“__index”和“__newindex”方法的metatable来定义索引/分配行为。

下面是一个完整的、可工作的示例,将静态数组公开给Lua。您的程序可能会有一些其他调用来将数组返回给Lua。请注意,没有任何边界检查;如果尝试超出数组边界进行索引,程序将崩溃。为了使程序更加健壮,您需要将userdata更改为具有数组指针和数组大小的结构,以便进行边界检查。

#include "lauxlib.h"

// 用于处理“array[index]”的metatable方法
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;
}

// 用于处理“array[index] = value”的metatable方法
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;
}

// 为我们的数组类型创建一个metatable
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);
}

// 通过使用数组metatable将其存储在userdata中,向lua公开数组
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;
}

// 测试数据
int mydata[] = { 1, 2, 3, 4 };

// 将我们的测试数组暴露给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);

   // 使我们的测试程序对Lua可用
   lua_register(L, "array", getarray);
   return 0;
}

用法:

require 'array'

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

-- 在C中设置初始值
print(foo[1])
print(foo[2])
print(foo[3])
print(foo[4])

-- 更改一些值
foo[1] = 2112
foo[2] = 5150
foo[4] = 777

-- 查看更改
print(foo[1])
print(foo[2])
print(foo[3])
print(foo[4])
2012-07-27 17:28:55