//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.
Hombre, no puedo creer cuánto apesta este código: P – Puppy
¿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'. –
Estoy bastante seguro de que definitivamente dejé esa parte. Probablemente junto con muchas otras partes útiles. – Puppy