lua-users home
lua-l archive

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


> var
>   TestObj : ^TTestObj;
> begin
>   TestObj := lua_newuserdata(luaVM, sizeOf(TTestObj));
>   TestObj^.property := 500;   //    <--- this causes an exception
> end;

Usually I do:

var
  TestObj: TTestObj;
begin
  TestObj:= TTestObj(lua_newuserdata(luaVM, SizeOf(TTestObj))^);
  TestObj.Property:= 500;
  { ... }
end;

Note1: A class will always be 4 byte long, because a class is just a pointer. Note2: An object (type TObj = object { ... } end; ) size won't be constant, because it is just a record (struct) with methods. Note3: This code is optimistic, it don't check if the result of lua_newuserdata is nil or not (the code is just an example, after all)

Also, I think I figured out how to use metatables for exposing
functions (eg. lua code:    myObj:setSize(10)), but how do I expose
properties?  (for example, in lua code:  myObj:size = 10)

Properties are a pain to implement, because Lua's mechanism to read/write fields in a table isn't easily compatible with Delphi's.

Usually you would have to implement __index and __newindex metamethods, checking field by field:

function l_TMyObject__index(L: PLuaState): Integer; cdecl;
var
  s: string;
  o: TMyObject;
begin
  // stack 1 = object userdata
  // stack 2 = name of the field
  o:= TMyObject(lua_touserdata(L, 1)^);
  s:= lua_tostring(L, 2);
  Result:= 1;
  if s = 'MyProperty' then
    lua_pushstring(L, PChar(O.MyProperty))
  else if s = 'AnotherProperty' then
    lua_pushnumber(L, O.AnotherProperty)
  else if ...
  else
    Result:= 0;
end;

You could also use RTTI to query those values, but it would only work with published properties (meaning: if you can edit a property with Object Inspector, then you can make it visible to Lua automatically, if you can't edit it in OI, then you have to publish it 'manually').

The main problem with this solution is that a metatable can only have one function for each metamethod, so you would have to mix properties getters/setters with methods. Meaning: you can't have a table of functions for the __index metamethod to search automatically. You would have to:

a) find it by yourself:
if s = 'myfunction' then
  lua_pushcfunction(L, @l_myfunction)
else if s = 'myotherfunction' then
  lua_pushcfunction(L, @l_myotherfunction)
else if ...

b) Create a table of functions and just say:
// Get the method table from registry
lua_pushstring(L, 'TMyObject$methods');
lua_gettable(L, LUA_REGISTRYINDEX);

// Push the property/function name
lua_pushstring(L, lua_tostring(L, 2));

// and get it from 'TMyObject$methods' table
lua_gettable(L, -2);

// Return it to Lua
Result:= 1;


Both solutions are very slow, compared to Lua's native way of handling __[new]index metamethod using plain tables.

Sorry for the long post, I hope this text can be of any help for you.