2010-04-05 13 views
7

Ho un progetto C++, dove 1 metodo di una classe 1 cambia molto spesso. Quindi voglio prendere quel codice da C++ a Lua. Nota, sono novizio di Lua.Passare l'oggetto C++ alla funzione Lua

L'intera operazione:

  1. Bind alcuni metodi della classe a macchina a stati Lua;
  2. Passa il riferimento all'oggetto classe a una funzione, scritto in Lua;
  3. Operare con oggetto C++ passato nella funzione Lua.

Ho trovato come fare il primo passo con Lunar, e non posso farcela con il secondo e il terzo.

Non riesco a utilizzare SWIG e boost.

risposta

7
//This has a large number of steps, but I'm gonna post them all. This is all using native Lua 5 and the lua CAPI. 
int CreateInstanceOfT(lua_State* L) { 
    new (lua_newuserdata(L, sizeof(T))) T(constructor args); 
    return 1; 
} 
int CallSomeFuncOnT(lua_State* L) { 
    if (lua_istable(L, 1)) { // If we're passed a table, get CData 
     lua_getfield(L, 1, "CData"); 
     lua_replace(L, 1); 
    } 
    if (!lua_touserdata(L, 1)) 
     lua_error(L); // longjmp out. 
    T& ref = *(T*)lua_touserdata(L, 1); 
    ref.SomeFunc(); // If you want args, I'll assume that you can pass them yourself 
    return 0; 
} 
int main() { 
    lua_State* L = luaL_newstate(); 
    lua_pushcfunction(L, CreateInstanceOfT); 
    lua_setglobal(L, "CreateInstanceOfT"); 
    lua_pushcfunction(L, CallSomeFuncOnT); 
    lua_setglobal(L, "CallSomeFuncOnT"); 
    luaL_dofile(L, "something.lua"); 
    lua_close(L); 
} 
-- Accompanying Lua code: semicolons are optional but I do out of habit. In something.lua 
function CreateCInstance() 
    local Instance = { 
     CData = CreateInstanceOfT(); 
     SomeFunc = CallSomeFuncOnT; 
    } 
    return Instance; 
end 

local object = CreateCInstance(); 
object:SomeFunc(); // Calls somefunc. 

ho potuto inviare una grande quantità di dettagli su come rendere più facile l'esposizione, e come fare l'ereditarietà, e simili - e avrà bisogno di alterare se si vuole esporre più di un T (credo che il la soluzione più comune è un semplice accordo struct { std::auto_ptr<void>, int type }). Ma dovrebbe essere un punto di partenza se non capisci nulla di questo processo.

Bascalmente, in primo luogo, chiediamo a Lua di allocare un po 'di spazio (i dati utente), quindi inserire T in esso. Quando viene visualizzato CallSomeFuncOnT, prima chiediamo se abbiamo una tabella (molte classi Lua sono basate su tabelle, poiché supportano l'orientamento degli oggetti, i metacli e così via) e ottengono i dati utente, che poi convertiamo in un puntatore al nostro oggetto, quindi convertirlo in un riferimento. Ricorda che lua_touserdata ti dà un vuoto *, quindi è meglio che tu sia dannatamente sicuro di ciò che è dall'altra parte. Quindi chiamiamo somefunc e ritorniamo. In Main, registriamo semplicemente le funzioni come globali.

Ora, in Lua, quando si chiama CreateInstanceOfT, chiama in modo efficace il costruttore T, in modo trasparente all'utente Lua. Poi lo buttiamo in un tavolo, che è più semplice per i novizi di Lua, e chiamiamo SomeFunc passandogli questa tabella.

+1

Uomo, non posso credere quanto questo codice faccia schifo: P – Puppy

+0

Mi sbaglio, o è vero che il distruttore di T non viene mai chiamato usando questa tecnica? A quanto ho capito, Lua non sa nulla degli oggetti C++ e chiama semplicemente 'free' per la memoria che controlla, come quella allocata da' lua_newuserdata'. –

+0

Abbastanza sicuro di aver lasciato definitivamente quella parte. Probabilmente insieme a molte altre parti utili. – Puppy

1

Hai dato un'occhiata a luabind? Rende abbastanza facile esporre oggetti e funzioni C++ a LUA.

+0

Sì, ho. Come accennato su http://www.rasterbar.com/products/luabind/docs.html utilizza boost – peterdemin

0

Come John, ho usato luabind e lo consiglio. Tuttavia, poiché l'utilizzo di boost non è un'opzione per te, potresti trovare utile il list of libraries on this page. Potresti anche voler controllare lo DoItYourselfCppBinding page on the lua-users wiki.

Una libreria menzionata nella pagina è oolua, che non ha dipendenze (così dice).

+0

Non riesco a credere, ho bisogno di qualche libreria per un'operazione così facile. – peterdemin

+0

Ricorda che puoi sempre utilizzare l'API Lua C ed eseguire autonomamente il binding. Le librerie sono lì per rendere "più facile" associare le classi C++ a Lua. –

+0

Zack l'affermazione è corretta, OOLua richiede solo su Lua. – user244655

Problemi correlati