9

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?

3
  • Since lua is intended as an embeddable language to interface nicely with C, I would expect the lua documentation to provide ample examples. Did you browse this information already? Commented Jul 27, 2012 at 13:56
  • Thanks for a fast answer. I have looked almost any documentation, but I cant find examples with pointer to array. Commented Jul 27, 2012 at 14:14
  • It's Lua, not LUA. It's not an acronym; it's a name. Commented Jul 27, 2012 at 19:22

1 Answer 1

23

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])
Sign up to request clarification or add additional context in comments.

2 Comments

Wow I can't thank you enough for this brilliant post with working examples. This is what I am looking for so thanks again! I am new to this forum how can I give points to you?
for starters, like myself i really appreciated the ease of use of luabind - for your simply issue you see that a lot of code is required to do it directly in lua - with luabind, thats basically a one liner - you should check it out here is a great intro blog.nuclex-games.com/tutorials/cxx/luabind-introduction - after you get more comfortable with things, developing directly in lua is still better tho - however with luabind you can basically do alot of things very fast to get a working concept

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.