I have really Googled this question but I never really got an solution.
I want to share an Array between C and Lua, for performance I will avoid copying Arrays to and from 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.
Example in C code
I want to define my array
int mydata[] = {1,2,3,4}
set it global to access it from Lua with the name mydata
.
In Lua
I want to change the values like this
mydata[3] = 9
and when I return to C, mydata[3]
is 9 because it is a pointer to the array.
How is this possible?
However, it is customary in Lua to start arrays with index 1. The Lua libraries adhere to this convention; so, if your arrays also start with 1, you will be able to use their functions directly. Such constructors can be as large as you need (well, up to a few million elements).
In Lua, arrays are implemented using indexing tables with integers. The size of an array is not fixed and it can grow based on our requirements, subject to memory constraints.
Yes, the arrays in Lua start with index 1 as the first index and not index 0 as you might have seen in most of the programming languages.
Definition of Lua Array. An array is used to store the elements in Lua, array represents the ordered set of an object that we store inside it. Array can be one dimensional or multi-dimensional in Lua.
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
.
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.
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;
}
Usage:
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])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With