我在Delphi + Lua上创建了一个简单的项目,通过RTTI使用Delphi可视化组件。基于luna.h
的主要实现思路。我喜欢Blizzard使用存储在xml中的模板的想法(例如,当您可以在TPanel上放置几个对象并将其用作模板时),所以我几乎也实现了它。
问题是:一切正常,直到我通过Lua回调创建对象,使用与luna.h
注入代码几乎相同的代码。如果此对象具有“继承”xml属性,则回调函数调用创建存储在xml中的对象,通过另一次注入创建另一个对象。我收到导致lua51.dll的错误。
当回调函数未返回结果时,可能由回调和Inject使用堆栈引起的问题。那么我可以使用堆栈并通过回调创建对象吗?如果没有 - 是否有任何解决方法来实现它?暴雪真的以某种方式成功了。
更多细节:
1.通过
TPanel
和许多其他对象)的应用程序
cn := T.ClassName;
f := @StaticOnCreate;
lua_pushlightuserdata(L, self); // put offset to self into lightuserdata
lua_pushcclosure(L, f, 1);
lua_setglobal(L, PAnsiChar(UTF8Encode(cn))); // T() in lua will make a new instance.
与luna.h的区别 - 应用程序还存储指向对象的指针(Delphi对象是指针)以避免泛型(c模板)
2.现在Lua在全局表中有TPanel
3.使用
p = TPanel("somename")
在脚本中,Lua调用应用程序的StaticOnCreate 4. StaticOnCreate提取对象并调用类的函数
o := TLuaClassTemplate(lua_topointer(L, lua_upvalueindex(1)));
result := o.OnCreate(L);
5。 OnCreate
函数提取name
之类的参数,并创建TPanel
类型的精确视觉对象,并使用与luna.h
函数相同的代码{/ 1}}
inject
通过堆栈返回Lua对象,所以现在来自 lua_newtable(FL); // create a new table for the class object ('self')
obj_index := lua_gettop(FL);
lua_pushnumber(FL, 0);
a := lua_newuserdata(FL, SizeOf(pointer)); // store a ptr to the ptr
a^ := obj; // set the ptr to the ptr to point to the ptr... >.>
luaL_newmetatable(FL, PAnsiChar(UTF8Encode(cn))); // get (or create) the classname_metatable
lua_pushstring(FL, PAnsiChar(UTF8Encode('__gc')));
lua_pushlightuserdata(FL, self); // put offset to self into lightuserdata
lua_pushcclosure(FL, @StaticGc_T, 1);
lua_settable(FL, -3);
lua_setmetatable(FL, -2); // userdata.metatable = classname_metatable
lua_settable(FL, obj_index); // self[0] = obj;
f := @StaticThunk;
// register the functions
for i := 0 to length(ClassApiArray) - 1 do begin
lua_pushstring(FL, PAnsiChar(UTF8Encode(ClassApiArray[i].name)));
lua_pushlightuserdata(FL, self); // put offset to self into lightuserdata
lua_pushnumber(FL, i); // let the thunk know which method we mean
lua_pushcclosure(FL, f, 2);
lua_settable(FL, obj_index); // self["function"] = thunk("function")
end;
lua_pushvalue(FL, -1); // dup object on stack top
rec.ref := luaL_ref(FL, LUA_REGISTRYINDEX); // store object as ref
...
result := 1;
的p是对象isntance。
但如果我尝试实施xml模板和第3步
,则会出现问题p = TPanel("somename")
并且在p = TPanel("somename", "xmltemplatenodename")
执行步骤5期间,如果我看到OnCreate
。因此,在步骤5中,在inherits = xmltemplatenodename
之前,应用程序搜索精确inject
- 如果找到,则为每个对象创建更多具有xmltemplatenodename
的对象。然后只有在继续使用自己的inject
执行第5步之后。在从inject
创建2-3个对象后,我有错误导致lua51.dll。但是,如果应用程序使用相同的xml作为源并在xmltemplatenodename
之外创建相同的xmltemplatenodename
对象 - 则没有错误。
OnCreate
对于xml对象略有不同,而不是将对象留在堆栈中,而是按对象名称注册它
Inject