在 lua 和 C 之间共享数组 [英] Share Array between lua and C

查看:18
本文介绍了在 lua 和 C 之间共享数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的在谷歌上搜索过这个问题,但我从来没有真正得到解决方案.

I have really Googled this question but I never really got an solution.

我想在 C 和 Lua 之间共享一个数组,为了性能我将避免从 Lua 复制数组.

I want to share an Array between C and Lua, for performance I will avoid copying Arrays to and from Lua.

所以我想将一个指向数组的指针从 C 传递给 Lua.然后从 Lua 我想直接设置/修改这个数组中的值.

So I want to pass a pointer to the Array from C to Lua. And then from Lua I want to set/modify values in this array directly.

C 代码示例

我想定义我的数组

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

将其设置为全局以从 Lua 使用名称 mydata 访问它.

set it global to access it from Lua with the name mydata.

在 Lua 中

我想改变这样的值

mydata[3] = 9

当我返回 C 语言时,mydata[3] 是 9,因为它是一个指向数组的指针.

and when I return to C, mydata[3] is 9 because it is a pointer to the array.

这怎么可能?

推荐答案

您可以通过 userdata 向 Lua 公开任意数据.如果你给你的用户数据值一个元表,你可以为这些用户数据定义各种操作符/操作的行为.在这种情况下,我们想向 Lua 公开一个数组并定义在 array[index]array[index] = value 的情况下要做什么.

You can expose arbitrary data to Lua via userdata. If you give your userdata values a metatable, you can define the behavior for various operators/operations on those userdata. In this case, we want to expose an array to Lua and define what to do in the case of array[index] and array[index] = value.

我们通过创建一个足够大的用户数据缓冲区来将数组暴露给 Lua,以保存数组的地址.我们通过使用 __index__newindex 方法创建元表来定义索引/分配行为.

We expose the array to Lua by creating a userdata buffer large enough to hold the address of the array. We define the indexing/assignment behavior by created a metatable with the __index and __newindex methods.

下面是一个完整的工作示例,它向 Lua 公开了一个静态数组.您的程序可能会有一些其他调用来将数组返回给 Lua.请注意,根本没有边界检查;如果您尝试在数组边界之外进行索引,则会崩溃.为了使其更健壮,您需要将用户数据更改为具有数组指针和数组大小的结构,以便您可以进行边界检查.

Below is a complete, working example that exposes a static array to Lua. Your program will probably have some other call for returning the array to Lua. Note, there's no boundschecking at all; if you try to index outside the array bounds, you'll crash. To make this more robust, you'd want to change the userdata to a structure which has the array pointer and the array size, so you can do boundschecking.

#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])

这篇关于在 lua 和 C 之间共享数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆