Pregunta

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

Editado:

intentará explicar más simple en pseudocódigo:

Lua:

local test = Object(); 

C:

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

Lua: hace un nuevo método

function test.newMethod() 
    ... 
end 

En C algún evento (digamos un temporizador) activa el método 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 
}

así que la pregunta es: cómo en C almacenar el puntero a algún objeto Lua (espero que lo necesite), obtener el objeto Lua por ese puntero y llamar al método en él

¿Fue útil?

Solución

Supongo que desea poder invocar funciones agregadas dinámicamente. Este código debería explicarlo de manera relativamente simple. Tenga en cuenta que no compruebo muchos errores y hago algunas suposiciones, no copie y pegue esto como una solución.

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

Comprueba eso, creo que eso es lo que buscas.

Otros consejos

Si todo lo que quiere es llamar a la función Lua `test.newMethod () ', entonces creo que quiere algo del orden de esto:

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

No creo que necesite meterse con una metatabla o datos de usuario.

Sin embargo, la fuerza de su pregunta no es del todo clara para mí ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top