문제

#1 Lua :

local test = Test();

#2 C :

//creating "lua's test"
luaL_newmetatable(L, "someTable");
lua_userdata *userData = (lua_userdata *)lua_newuserdata(L, sizeof(lua_userdata));

luaL_getmetatable(L, "someTable");
lua_setmetatable(L, -2);

#3 LUA :

function test.newMethod()
end

#4 C :

//this part is not executed from Lua
//what i have to have here from #2 to call "test.newMethod" and how to call it?
//if userdata would be on stack i guess i could:
luaL_getmetafield (L, 1, "newMethod");
lua_call(L, 0, 0);
//but because this part is not executed by Lua call its not on stack.

편집 :

의사 코드에서 더 간단하게 설명하려고합니다.

루아 :

local test = Object(); 

씨:

int Object(){ 
    ... 
    somePointer = luaL_newmetatable(...); //how to get this "somePointer"? maybe luaL_ref?
    push ... 
} 

LUA : 새로운 방법을 만듭니다

function test.newMethod() 
    ... 
end 

C에서 일부 이벤트 (타이머라고 가정하자)에서 C 메소드를 트리거합니다.

void triggeredCMethod(){ 
    //here i need to call test.newMethod 
    //if i would have here 'somePointer' and could push it to Lua stack i could find and call newMethod 
}

그래서 질문은 다음과 같습니다. C 스토어에서 일부 LUA 객체에 대한 포인터 (필요한 희망).

도움이 되었습니까?

해결책

동적으로 추가 된 기능을 호출 할 수 있다고 가정합니다. 이 코드는 비교적 간단하게 설명해야합니다. 참고 오류 검사가별로없고 몇 가지 가정을하지 않으며이 책을 솔루션으로 복사하지 마십시오.

typedef struct
{
    int number;
    int reference;
    lua_State *L;
} TestUserdata;

static int m_newindex( lua_State *L )
{
    /* This is passed three values, first ( at -3 ) is the object, bring this to the front */
    lua_getfenv( L, -3 );
    /* Now bring the second arg forward, the key */
    lua_pushvalue( L, -3 );
    /* And the third arg, the value */
    lua_pushvalue( L, -3 );
    /* And we're done */
    lua_rawset( L, -3 );

    return 0;
}

static int m_tostring( lua_State *L )
{
    lua_pushstring( L, "TestUserdata" );
    return 1;
}

static int callobject( lua_State *L )
{
    /* Grab the object passed, check it's the right type */
    TestUserdata *data = luaL_checkudata( L, 1, "TestUserdata" );

    /* Grab the function environment we gave it in createobject, and look in there for newmethod */
    lua_getfenv( L, -1 );
    lua_pushstring( L, "newmethod" );
    lua_rawget( L, -2 );

    /* Call the function */
    lua_pushinteger( L, data->number );
    lua_call( L, 1, 0 );

    return 0;
}

static const struct luaL_reg userdata_m[] = {
    { "__newindex", m_newindex },
    { "__tostring", m_tostring },
    { NULL, NULL }
};

int main (int argc, char *argv[])
{
    lua_State *L = luaL_newstate();
    luaL_openlibs( L );

    /* Let's create us a userdatum metatable, and fill it up with goodies */
    luaL_newmetatable( L, "TestUserdata" );
    /* Use luaL_register to fill up the metatable for us */
    luaL_register( L, NULL, userdata_m );
    lua_pop( L, 1 ); /* Clean up the stack, we won't need the metatable left here */

    TestUserdata *data = lua_newuserdata( L, sizeof( TestUserdata ) );
    lua_pushvalue( L, -1 ); /* Copy for luaL_ref */
    int ref = luaL_ref( L, LUA_REGISTRYINDEX );
    data->reference = ref;
    data->number = 42;
    data->L = L;

    /* Load the metatable from before and 'give' it to this userdatum */
    luaL_getmetatable( L, "TestUserdata" );
    lua_setmetatable( L, -2 );

    /* Give this object an empty function environment */
    lua_newtable( L );
    lua_setfenv( L, -2 );

    lua_setglobal( L, "test" );

    luaL_dostring( L, "function test.newmethod( num ) print( num ) end" );

    /* Now provided we have the object, we can call any method defined anywhere */
    lua_rawgeti( data->L, LUA_REGISTRYINDEX, data->reference );
    lua_getfenv( data->L, -1 );
    lua_pushstring( data->L, "newmethod" );
    lua_rawget( data->L, -2 );
    lua_remove( data->L, -2 );

    if( lua_isfunction( data->L, -1 ) == 1 )
    {
        lua_pushinteger( data->L, data->number );

        lua_pcall( data->L, 1, 0, 0 );
    }

    lua_close( L );

    return 0;
}

확인, 나는 그것이 당신이 추구하는 것이라고 생각합니다.

다른 팁

LUA 함수`test.newmethod () '라고 부르는 것이 당신이 원하는 것은 당신이 이것의 순서에 따라 무언가를 원한다고 생각합니다.

lua_getglobal(L, "test");
lua_getfield(L, -1, "newMethod");
lua_call(L, 0, 0);

나는 당신이 중족단이나 사용자 데이터를 엉망으로 만들 필요가 없다고 생각합니다.

그러나 당신의 질문의 힘은 나에게 완전히 명확하지 않습니다 ...

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top