2012-07-27 1 views
5

나는 정말로이 질문을 봤다. 그러나 나는 결코 해결책을 얻지 못했다.루아와 C 사이의 공유 배열

C와 Lua간에 배열을 공유하고 싶습니다. 성능을 위해 Lua와의 배열 복사를 피할 것입니다.

그래서 C 배열에서 Lua 포인터를 전달하고 싶습니다. 그리고 Lua에서이 배열의 값을 직접 설정하거나 수정하려고합니다. C 코드에서


나는 나의 배열이 글로벌 이름 mydata와 루아에서 액세스 할 수

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

세트를 정의하고 싶다.


루아

에서 I이

mydata[3] = 9 

같은 값을 변경할 및 I는 C로 돌아갈 때 배열 포인터 때문에 mydata[3] 9이다.

어떻게 가능합니까?

+0

루아는 C로 잘 인터페이스에 내장 가능한 언어로 구성되어 있기 때문에, 내가 루아 문서가 충분한 예제를 제공 할 것으로 예상한다. 이 정보를 이미 살펴 보았습니까? – Jens

+0

빠른 답변 주셔서 감사합니다. 거의 모든 문서를 보았지만 배열에 대한 포인터를 사용하여 예제를 찾을 수 없습니다. – user1557786

+0

루아가 아니라 루아예요. 두문자어가 아닙니다. 그것은 이름입니다. –

답변

19

임의의 데이터를 userdata을 통해 Lua에 공개 할 수 있습니다. 사용자 데이터 값 을 metatable으로 지정하면 해당 사용자 데이터에서 다양한 연산자/연산에 대한 동작을 정의 할 수 있습니다. 이 경우 배열을 Lua에 노출하고 array[index]array[index] = value의 경우 수행 할 작업을 정의하려고합니다.

우리는 배열의 주소를 담을 수있을만큼 큰 사용자 데이터 버퍼를 생성하여 Lua에 배열을 노출시킨다. __index__newindex 메소드로 메타 테이블을 만들어 색인/할당 동작을 정의합니다.

다음은 정적 배열을 루아에 노출시키는 완전한 작업 예제입니다. 프로그램은 아마도 배열을 루아로 되돌려 줄 다른 요청을 할 것이다. 여기에는 경계 체크가 전혀 없습니다. 배열 경계 밖에서 색인하려고하면 충돌이 발생합니다. 이것을보다 강력하게 만들기 위해서는 배열 포인터와 배열 크기를 가진 구조체로 userdata를 변경하여 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; 
} 

사용법 :

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

와우 나는이 훌륭한 게시물에 대해 작업 예제로 충분히 감사 할 수 없습니다. 이것은 내가 다시 찾고있는 덕분입니다. 이 포럼을 처음 접한다면 어떻게 할 수 있습니까? – user1557786

+1

처음에는 luabind 사용의 용이함을 정말 고맙게 생각합니다. 루아 바인드와 함께 루아 바인드에서 코드를 직접 수행해야한다는 간단한 문제가 있습니다. 루아 바인드는 기본적으로 하나의 라이너입니다. 체크 아웃해야합니다. 여기에 훌륭한 소개 http://blog.nuclex-games.com/tutorials/cxx/luabind-introduction/- 당신이 일을 더 편안하게하고 나면, 루아에서 직접 개발하는 것이 여전히 더 나은 것입니다 - 그러나 루아 바인드를 사용하면 기본적으로 할 수 있습니다 일하는 개념을 얻기 위해 매우 빠른 것들을 많이 봅니다. – Steve