Question

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

Modifié:

essayera d'expliquer plus simplement dans le pseudo-code:

Lua:

local test = Object(); 

C:

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

Lua: crée une nouvelle méthode

function test.newMethod() 
    ... 
end 

En C, certains événements déclenchent la méthode 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 
}

la question est donc: comment dans le magasin C pointeur sur un objet Lua (j'espère en avoir besoin), obtenez l'objet Lua par ce pointeur et appelez-y la méthode

Était-ce utile?

La solution

Je suppose que vous voulez pouvoir appeler des fonctions ajoutées dynamiquement. Ce code devrait l'expliquer relativement simplement. Notez que je ne fais pas beaucoup de vérifications d'erreur et que je fais quelques hypothèses, ne copiez pas ceci comme solution.

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

Vérifiez cela, je pense que c'est ce que vous recherchez.

Autres conseils

Si vous souhaitez simplement appeler la fonction Lua `test.newMethod () ', alors je pense que vous souhaitez quelque chose dans l'ordre suivant:

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

Je ne pense pas que vous ayez besoin de jouer avec une métable ou une donnée utilisateur.

Cependant, la force de votre question ne m'est pas tout à fait claire ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top