[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Simple example of sharing data (and objects) between C++ and Lua?
- From: Romulo Bahiense <romulo@...>
- Date: Fri, 09 Dec 2005 13:17:13 -0300
> 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.