Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Share Array between lua and C

Tags:

c

lua

lua-table

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?

like image 620
user1557786 Avatar asked Jul 27 '12 13:07

user1557786


People also ask

Do arrays start at 0 or 1 Lua?

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).

Does Lua have array?

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.

Are Lua arrays 0 based?

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.

What is a Lua array?

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.


1 Answers

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])
like image 101
Mud Avatar answered Sep 19 '22 10:09

Mud