2010-04-05 11 views
7

Tengo un proyecto C++, donde 1 método de una clase cambia muy a menudo. Entonces quiero tomar ese código de C++ a Lua. Tenga en cuenta que soy novato de Lua.Pase el objeto C++ a la función Lua

toda la tarea:

  1. Enlazar algunos métodos de la clase a la máquina de estados Lua;
  2. Pasa la referencia al objeto de clase a una función, escrito en Lua;
  3. Operar con objeto C++ pasado en la función Lua.

He encontrado cómo dar el primer paso con Lunar, y no puedo lidiar con el segundo y el tercero.

No puedo usar SWIG y boost.

Respuesta

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. 

pude publicar una gran cantidad de detalles acerca de cómo hacer más fácil la exposición, y cómo hacer que la herencia, y cosas por el estilo - y necesitará alterar si desea exponer más de una T (creo que el la solución más común es una simple oferta de struct { std::auto_ptr<void>, int type }). Pero, debería ser un punto de partida si no entiende nada sobre este proceso.

En primer lugar, le pedimos a Lua que asigne un espacio (los datos de usuario), luego coloque la letra T en él. Cuando aparece CallSomeFuncOnT, primero le preguntamos si tenemos una tabla (muchas clases de Lua se basan en tablas, ya que admiten orientación de objetos, metatablas, etc.) y sacamos los datos de usuario, que luego convertimos en un puntero a nuestro objeto, y luego convertir en una referencia. Recuerda que lua_touserdata te da un vacío *, así que será mejor que estés seguro de lo que hay al otro lado. Entonces llamamos a somefunc y volvemos. En Main, solo registramos las funciones como globales.

Ahora, en Lua, cuando llama a CreateInstanceOfT, efectivamente llama al constructor T, de forma transparente para el usuario de Lua. Luego lo desechamos en una mesa, que es más simple para los novatos Lua, y llamamos SomeFunc pasando esta tabla.

+1

Hombre, no puedo creer cuánto apesta este código: P – Puppy

+0

¿Estoy equivocado, o es cierto que el destructor de T nunca se llama usando esta técnica? Según tengo entendido, Lua no sabe nada acerca de los objetos C++ y simplemente llama a 'free' para la memoria que controla, como la asignada por' lua_newuserdata'. –

+0

Estoy bastante seguro de que definitivamente dejé esa parte. Probablemente junto con muchas otras partes útiles. – Puppy

1

¿Has echado un vistazo a luabind? Hace que sea bastante fácil exponer objetos y funciones de C++ a LUA.

+0

Sí, tengo. Como mencioné en http://www.rasterbar.com/products/luabind/docs.html usa boost – peterdemin

0

Como John, he usado luabind y lo recomiendo. Sin embargo, dado que usar el impulso no es una opción para usted, puede encontrar útil el list of libraries on this page. También es posible que desee comprobar el DoItYourselfCppBinding page on the lua-users wiki.

Una biblioteca mencionada en la página es oolua, que no tiene dependencias (por lo que dice).

+0

. No puedo creer que necesite una biblioteca para una operación tan fácil. – peterdemin

+0

Tenga en cuenta que siempre puede usar la API Lua C y realizar el encuadernado usted mismo. Las bibliotecas están ahí para hacer que sea "más fácil" vincular las clases de C++ a Lua. –

+0

Zack la declaración es correcta, OOLua solo requiere en Lua. – user244655

Cuestiones relacionadas