I recommend you create a userdata that exposes the arrays via __index
and __newindex
, something like this (written as a C and C++ polyglot like Lua itself):
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <lua5.3/lua.h>
#include <lua5.3/lauxlib.h>
#ifdef __cplusplus
}
#endif
struct MyNumbers {
lua_Number *arr;
lua_Integer len;
};
int MyNumbers_index(lua_State *L) {
struct MyNumbers *t = (struct MyNumbers *)luaL_checkudata(L, 1, "MyNumbers");
lua_Integer k = luaL_checkinteger(L, 2);
if(k >= 0 && k < t->len) {
lua_pushnumber(L, t->arr[k]);
} else {
lua_pushnil(L);
}
return 1;
}
int MyNumbers_newindex(lua_State *L) {
struct MyNumbers *t = (struct MyNumbers *)luaL_checkudata(L, 1, "MyNumbers");
lua_Integer k = luaL_checkinteger(L, 2);
if(k >= 0 && k < t->len) {
t->arr[k] = luaL_checknumber(L, 3);
return 0;
} else {
return luaL_argerror(L, 2,
lua_pushfstring(L, "index %d out of range", k));
}
}
struct MyNumbers *MyNumbers_new(lua_State *L, lua_Number *arr, lua_Integer len) {
struct MyNumbers *var = (struct MyNumbers *)lua_newuserdata(L, sizeof *var);
var->arr = arr;
var->len = len;
luaL_setmetatable(L, "MyNumbers");
return var;
}
int main(void) {
const lua_Integer LENGTH = 512 * 256;
lua_Number input[LENGTH], output[LENGTH];
memset(output, 0, sizeof output);
for(lua_Integer i = 0; i < LENGTH; ++i)
input[i] = i + 0.5f;
lua_State *L = luaL_newstate();
luaL_newmetatable(L, "MyNumbers");
lua_pushcfunction(L, MyNumbers_index);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, MyNumbers_newindex);
lua_setfield(L, -2, "__newindex");
/* exercise for the reader: implement __len and __pairs too, and maybe shift the indices so they're 1-based to Lua */
lua_pop(L, 1);
MyNumbers_new(L, input, LENGTH);
lua_setglobal(L, "input");
MyNumbers_new(L, output, LENGTH);
lua_setglobal(L, "output");
luaL_dostring(L, "output[10] = input[256]");
lua_getglobal(L, "output");
lua_geti(L, -1, 10);
lua_Number val = lua_tonumber(L, -1);
printf("%f, %f, %f\n", input[256], output[10], val);
lua_close(L);
}
With this approach, there is no copy of any data in Lua, and your own MyNumbers_
functions control how all access to them is done.
If you want to be able to use the arrays through LuaJIT’s FFI instead of directly manipulating them in Lua, then you can pass their addresses in a light userdata instead, like this:
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <luajit-2.0/lua.h>
#include <luajit-2.0/lualib.h>
#include <luajit-2.0/lauxlib.h>
#ifdef __cplusplus
}
#endif
int main(void) {
const lua_Integer LENGTH = 256 * 512;
lua_Number input[LENGTH], output[LENGTH];
memset(output, 0, sizeof output);
for(lua_Integer i = 0; i < LENGTH; ++i)
input[i] = i + 0.5f;
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_pushlightuserdata(L, input);
lua_setglobal(L, "input");
lua_pushlightuserdata(L, output);
lua_setglobal(L, "output");
lua_pushinteger(L, LENGTH);
lua_setglobal(L, "LENGTH");
luaL_dofile(L, "my_script.lua");
lua_close(L);
}
CLICK HERE to find out more related problems solutions.