lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi,

jdarling@eonclash.com wrote:
> Sorry for duplicate messages on the same topic, but by chance do you
> still have some sample Delphi code lying around of how you wrapped up
> objects?

Sorry for the delay. I'm quite busy fighting a disturbing hardware problem.

About your problem, I don't have at hand one isolated example for your, because it is a bit entangled with my closed library.

But a solution I use is something like:

One table containing the class' methods, ieg:

TFooMethods = {
  bar = <cfunction>,
  baz = <cfunction>,
  ...
}

(This table is populated on the luaopen_mylibrary function)

And the object's (userdata's) metamethod is a function that:

Check if the requested name is a RTTI property. If it is, then return it as you was doing with your example. If it is not, then it will get that TFooMethods table from the registry and return it's value on the key specified by the first meta __index argument.

An example (again, not tested) would be:

function lua__index(L: PLuaState): Integer; cdecl;
var
  Obj: TObject;
  outvar: Variant;
begin
  Result:= 1;
  // Get a Delphi object from Lua world
  Obj:= GetObjFromLuaStack(L, 1);

  // Check if the field name is a property of that object
  if GetVCLProp(Obj, lua_tostring(L, 2), outvar) then
    PushLuaVariant(L, outvar)
  else
  begin
    // If it is not, get the (Obj.ClassName+'Methods')
    // table from registry
    lua_pushstring(L, Obj.ClassName+'Methods');
    lua_gettable(L, LUA_REGISTRYINDEX);
    if lua_istable(L, -1) then
    begin
      // If it is a table, then get it's value
      lua_pushvalue(L, 2);
      lua_gettable(L, -2)
    end
    else
      // Otherwise, push nil (nothing can be found with the
      // specified field name)
      lua_pushnil(L);
  end;
end;

And the functions in the TFooMethods table would be something like:

function lua_TFoo_bar(L: PLuaState): integer; cdecl;
begin
    Result:= 0;
    with GetTFooFromLuaStack(L, 1) do
      Bar(lua_tostring(L, 2));
end;

But this approach requires you to create one Lua C Function for each method in your class. This may sound bad, but from my experience, it is better that way -- less mess in your code and more performance in runtime. Plus, you are able to write more specialized code to interface with Lua, taking advantage of it's nature of dynamic types, anonymous functions (first-class values) and multiple return values.

A problem you may find is that you can't use RTTI's published methods (a.k.a. events). This is a pain the neck. A solution would be to implement some kind of RTTIJIT or TPC (Tinny Pascal Compiler ^^), but I don't have the knowledge nor the time, yet :)

Good luck!
--rb