1

我在 Delphi + Lua 上制作了一个简单的项目,通过 RTTI 使用 Delphi 可视化组件。主要实现思路基于luna.h. 我喜欢暴雪使用存储在 xml 中的模板的想法(例如,当您可以在 TPanel 上放置多个对象并将其用作模板时),所以我几乎也实现了这一点。

问题是:一切正常,直到我通过 Lua 的回调创建对象,该回调使用与luna.hInject 代码几乎相同的代码。如果此对象具有“继承”xml 属性,则回调函数调用存储在 xml 中的对象的创建,通过又一次注入创建另一个对象。我收到导致 lua51.dll 的错误。

可能是回调和 Inject 都使用堆栈导致的问题,而回调函数尚未返回结果。那么我可以使用堆栈并通过回调创建对象吗?如果没有 - 是否有任何解决方法来实施它?暴雪确实以某种方式做到了。

更多细节:
1.应用程序注册Lua对象(例如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. 现在 LuaTPanel在全局表中
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代码inject

  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;

通过堆栈返回 Lua 对象,所以现在 p fromp = TPanel("somename")是对象实例。

但是,如果我尝试实现 xml 模板和步骤 3

p = TPanel("somename", "xmltemplatenodename")

并且在执行步骤 5 中,OnCreate如果我看到有inherits = xmltemplatenodename. 因此,在第 5 步之前inject,应用程序搜索精确- 如果发现为每个对象xmltemplatenodename创建更多对象。inject并且只有在此之后继续使用 own 执行第 5 步inject。在从xmltemplatenodename. 但是,如果应用程序使用与源相同的 xml 并xmltemplatenodename在外部创建相同的对象OnCreate- 没有错误。

Inject对于 xml 对象略有不同,不是将对象留在堆栈中,而是通过对象名称注册它

  lua_setglobal(FL, PAnsiChar(objName8));
4

0 回答 0