[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Problems with LUA 5.02 and user objects
- From: Romulo Bahiense <romulo@...>
- Date: Mon, 03 Apr 2006 16:45:01 -0300
Hi,
I think the problem is here:
if Assigned(m.Code) then
result := TLuaObjectMethod(m)(l)
else
result := 0;
You are calling the method in the instIndex function, returning it's
result. Lua expects you to return that function instead.
Suppose you have a class TFoo and a method bar(). When you instantiate a
Lua userdata for the TFoo class, and write something like this:
-- I don't know how your constructors looks like...
local foo = TFoo.Create()
foo:bar()
foo's __index metamethod should return a function to be executed by the
Lua VM and not on the "C side" (Delphi side ;).
Basically you would have to replace those lines with:
if Assigned(m.Code) then
begin
lua_pushcfunction(TLuaObjectMethod(m));
Result:= 1;
end
else
Result := 0;
But a problem arises here, because a method is different from a Lua C
Function. A method is a function that requires an implicit "Self"
reference as the first argument and n other arguments as the
function/procedure parameters, while a Lua C Function is a function that
accepts only a pointer to a lua_State structure (record) and returns an
integer (also, it has to be cdecl'ed). I think the best solution would
be to create a generic LuaCFunction which would have as it's first two
upvalues the parts of a TMethod record:
function dummycclosure(L: PLuaState): integer; cdecl;
var
m: TMethod;
begin
m.Data:= lua_touserdata(L, lua_upvalueindex(1));
m.Code:= lua_touserdata(L, lua_upvalueindex(2));
Result:= TLuaObjectMethod(m)(L);
end;
And your instIndex would be:
if Assigned(m.Code) then
begin
lua_pushlightuserdata(L, m.Data);
lua_pushlightuserdata(L, m.Code);
lua_pushcclosure(dummycclosure, 2);
Result:= 1;
end
else
Result := 0;
This solution should work fine, but it creates a C closure each time it
is called.
There are other solutions for you problem, as creating binding functions
for your class methods and then putting them into a table, perhaps
replacing the __index function with that table, and settings it's
__index metamethod for that __index function (confusing?).
I have tried to create a binding mechanism sometime ago but I had to
abandon it (cost x benefit). Most of the time, it is easier to create
the binding functions manually than to create a run-time system[1]
generic enough to accommodate both Delphi's and Lua's particularities. I
wish you to be more lucky than me :)
--rb
1. I tried to implement a run-time system to take advantage of Delphi's
RTTI. I think that an offline engine would be a bit simpler to implement.
ps: I have not tested any of the code I wrote.