2012-07-27 14 views
5

Mam naprawdę Googled to pytanie, ale nigdy nie dostałem rozwiązania.Share Array między lua i C

Chcę udostępnić Array między C i Lua, dla wydajności będę unikać kopiowania Tablice do iz Lua.

Więc chcę przekazać wskaźnik do tablicy od C do Lua. A potem z Lua chcę ustawić/zmodyfikować wartości bezpośrednio w tej tablicy.


przykład w kodzie C

chcę definiować moja tablica

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

zestaw to globalny do niego dostęp z Lua z nazwą mydata.


W Lua

Chcę zmienić wartości jak ten

mydata[3] = 9 

i kiedy wrócę do C, mydata[3] jest 9, ponieważ jest to wskaźnik do tablicy.

Jak to jest możliwe?

+0

Ponieważ Lua jest pomyślana jako języka do osadzenia na interfejs ładnie z C, spodziewałbym dokumentacja lua dostarczyć wiele przykładów. Czy przeglądałeś już te informacje? – Jens

+0

Dzięki za szybką odpowiedź. Mam prawie całą dokumentację, ale nie mogę znaleźć przykładów ze wskaźnikiem do tablicy. – user1557786

+0

To Lua, nie LUA. To nie jest akronim; to jest imię. –

Odpowiedz

19

Możesz ujawnić dowolne dane Lua przez userdata. Jeśli podasz swoje wartości danych użytkownika metatable, możesz zdefiniować zachowanie dla różnych operatorów/operacji na tych danych użytkownika. W tym przypadku chcemy odsłonić tablicę Lua i zdefiniować, co zrobić w przypadku array[index] i array[index] = value.

Ujawniamy tablicę Lua, tworząc bufor użytkownika o rozmiarze wystarczającym do przechowywania adresu tablicy. Definiujemy zachowanie indeksowania/przypisania, tworząc metatable metodami __index i __newindex.

Poniżej znajduje się pełny, działający przykład, który udostępnia statyczną tablicę Lua. Twój program prawdopodobnie będzie miał inne wezwanie do zwrócenia tablicy do Lua. Zauważ, że w ogóle nie ma żadnej kontroli; jeśli spróbujesz indeksować poza granicami tablicy, ulegniesz awarii. Aby było to bardziej niezawodne, należy zmienić dane użytkownika na strukturę, która ma wskaźnik tablicy i rozmiar tablicy, aby można było wykonywać kontrole.

#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; 
} 

Zastosowanie:

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]) 
+0

Wow, nie mogę ci wystarczająco podziękować za ten genialny post z przykładami pracy. Tego właśnie szukam, dzięki jeszcze raz! Jestem nowy na tym forum, w jaki sposób mogę dać ci punkty? – user1557786

+1

na początek, tak jak ja naprawdę doceniam łatwość użycia luabind - dla twojego prostego problemu widzisz, że wiele kodu jest wymagane, aby zrobić to bezpośrednio w lua - z luabind, to w zasadzie jeden liniowiec - powinieneś to sprawdzić tutaj jest świetne intro http://blog.nuclex-games.com/tutorials/cxx/luabind-introduction/ - po tym, jak będziesz mieć więcej wygody, rozwijanie bezpośrednio w Lua jest jeszcze lepsze - jednak z luabind możesz zrobić to samo wiele rzeczy bardzo szybko, aby uzyskać działającą koncepcję – Steve