마음의 안정을 찾기 위하여 - [Lua] 클래스 멤버함수를 루아글루 함수로 등록해서 사용할 수 있나요?
1961425
199
322
관리자새글쓰기
태그위치로그방명록
별일없다의 생각
dawnsea's me2day/2010
색상(RGB)코드 추출기(Color...
Connection Generator/2010
최승호PD, '4대강 거짓말 검...
Green Monkey**/2010
Syng의 생각
syng's me2DAY/2010
천재 작곡가 윤일상이 기획,...
엘븐킹's Digital Factory/2010
[Lua] 클래스 멤버함수를 루아글루 함수로 등록해서 사용할 수 있나요?
Web, Script/Lua | 2010/02/17 16:52
Q] 클래스 멤버함수를 루아글루 함수로 등록해서 사용할 수 있나요?

한번 시도는 해봤지만 타입이 안 맞는다는 에러문등이 뜨고 하네요. 제가 방법을 잘 모르는건지 아니면 원래 클래스의 멤버함수는 루아글루함수로 등록이 불가능한건지 궁금합니다. 고수님들의 답변 부탁드립니다.

A] 델마당의 게임제작 게시판에 제가 했던 삽질을 올려두었더니
http://www.delmadan...keyword2=&page=1

저 자신이 루아에 반쯤 미쳐있는 상태라 불필요한 정보를 한 줌 더 얹는
삽질일 수 있습니다만... 그래도 혹시나싶어 짧은 팁을 끄적여봅니다. ^^;;;

훅함수 등 대부분의 콜백들과 마찬가지로, 루아에서 호출되는 접착제함수(글루함수)
역시 전역함수여야 합니다. 그런데, 가끔은 객체 내부에 국한된 글루함수가 필요할
때도 있습죠. 대표적으로 동적으로 생성되는 객체의 메소드로 루아글루를 등록할 때가
이에 해당할 것입니다.

메시지 서브클래싱에 경험이 있다면, MakeObjectInstance 라는 함수를 사용해 객체마다
서로 다른 윈도프로시저를 지정하는 방법에 대해 익숙하실 겁니다. 다음 강좌 중간에
잠시 언급되어있으니 짚어두시구요~~
http://www.delphikorea.com /board2007/bbs/view.php?id=reallecture&page=1&sn1=& divpage=1&sn=off&ss=on&sc=on&keyword=훅& select_arrange=headnum&desc=asc&no=148

위 동작을 모방해서 객체 내에 정의한 lua_CFunction 타입의 함수의 인스턴스를
동적으로 만들어내는 MakeLuaGlueInstance 란 함수를 만들어봤습니다.

설명 생략하고 소스 주르륵 나갑니다. ^^



//=============================================================================
// 루아글루함수 인스턴스 생성

type
TLuaGlueMethod = function (L: lua_State) : Integer of object; cdecl;

TLuaGlueCall = packed record
L: lua_State;
R: Integer;
end;

const
INSTANCE_COUNT = 313;

type
PObjectInstance = ^TObjectInstance;
TObjectInstance = packed record
Code: Byte;
Offset: Integer;
case Integer of
0: (Next: PObjectInstance);
1: (Method: TLuaGlueMethod);
end;

PInstanceBlock = ^TInstanceBlock;
TInstanceBlock = packed record
Next: PInstanceBlock;
Code: array[1..2] of Byte;
LuaGlueProcPtr: Pointer;
Instances: array[0..INSTANCE_COUNT] of TObjectInstance;
end;


var
InstBlockList : PInstanceBlock = nil;
InstFreeList : PObjectInstance = nil;
DefaultMaxTable : integer = 256;


function StdLuaGlueProc(L: lua_State): Integer; cdecl;
asm
PUSH L
PUSH L
CALL [ECX].Pointer
ADD ESP,8
end;

function CalcJmpOffset(Src, Dest: Pointer): Longint;
begin
Result := Longint(Dest) - (Longint(Src) + 5);
end;

function MakeLuaGlueInstance(Method: TLuaGlueMethod): Pointer;
const
BlockCode: array [1..2] of Byte = ($59, $E9);
PageSize = 4096;
var
Block: PInstanceBlock;
Instance: PObjectInstance;
begin
if InstFreeList = nil then
begin
Block := VirtualAlloc (nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Block^.Next := InstBlockList;

Move(BlockCode, Block^.Code, SizeOf(BlockCode));
Block^.LuaGlueProcPtr :=
Pointer(CalcJmpOffset(@Block^.Code[2], @StdLuaGlueProc));

Instance := @Block^.Instances;

repeat
Instance^.Code := $E8;
Instance^.Offset := CalcJmpOffset(Instance, @Block^.Code);
Instance^.Next := InstFreeList;
InstFreeList := Instance;
Inc(Longint(Instance), SizeOf(TObjectInstance));
until Longint(Instance) - Longint(Block) >= SizeOf(TInstanceBlock);

InstBlockList := Block
end;

Result := InstFreeList;
Instance := InstFreeList;
InstFreeList := Instance^.Next;
Instance^.Method := Method
end;

procedure FreeLuaGlueInstance(ObjectInstance: Pointer);
begin
if ObjectInstance <> nil then
begin
PObjectInstance(ObjectInstance)^.Next := InstFreeList;
InstFreeList := ObjectInstance
end
end;


사용법은 MakeObjectInstance와 같습니다. 객체 내에 대강 다음과 같은
글루함수가 정의되어있다면

type
TForm1 = class(TForm)
......
function LuaStrFunc(L: lua_State): Integer; cdecl;
......

생성될 인스턴스를 저장할 포인터 변수를 정의하고

LuaStrFuncProc: Pointer;

MakeLuaGlueInsance()를 호출해주시면 됩니다.

LuaStrFuncProc := MakeLuaGlueInstance(LuaStrFunc);

이 제 이 인스턴스는 얼마든지 글루함수로 등록할 수 있습죠.

lua_register(L, 'LuaStrFunc', LuaStrFuncProc);

인스턴스를 해제할 때는 FreeLuaGlueInstance 를 쓰시면 됩니다.


짤 막 팁 끝~~!
저는 그만 자러갑니다. 좋은 밤 되시구요~~ ^^;;



프리맨님이 멋진 해법을 가르쳐 주셨습니다.
http://www.delmadan...keyword2=&page=1

type
TLuaGlueMethod = function (L: lua_State) : Integer of object; //주의) cdecl 빠집니다.

function lua_method_caller(L: Lua_State): Integer; cdecl;
var method: TLuaGlueMethod;
begin
TMethod(method).data:= lua_topointer(L, lua_upvalueindex(1));
TMethod(method).code:= lua_topointer(L, lua_upvalueindex(2));
Result:= method(L);
end;

procedure lua_method_register(L: Lua_State; const name: string; method: TLuaGlueMethod);
begin
lua_pushlightuserdata(L, TMethod(method).data);
lua_pushlightuserdata(L, TMethod(method).code);
lua_pushcclosure(L, lua_method_caller, 2);
lua_setglobal(L, name);
end;


등 록할땐...

lua_method_register(L, 'testmethod', Obj.TestMethod);


델파이로 된 코드입니다만... ^^


원문 출처 : http://gpgstudy.com/forum/viewtopic.php?p=100183#100183
2010/02/17 16:52 2010/02/17 16:52
Article tag list Go to top
View Comment 0
Trackback URL :: 이 글에는 트랙백을 보낼 수 없습니다
 
 
 
 
: [1] ... [274][275][276][277][278][279][280][281][282] ... [855] :
«   2021/11   »
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
전체 (855)
출판 준비 (0)
My-Pro... (41)
사는 ... (492)
블로그... (22)
My Lib... (32)
게임 ... (23)
개발관... (3)
Smart ... (1)
Delphi (75)
C Builder (0)
Object... (0)
VC, MF... (9)
Window... (1)
Open API (3)
Visual... (0)
Java, JSP (2)
ASP.NET (0)
PHP (4)
Database (12)
리눅스 (28)
Windows (23)
Device... (1)
Embedded (1)
게임 ... (0)
Web Se... (2)
Web, S... (19)
잡다한... (5)
프로젝트 (0)
Personal (0)
대통령... (9)
Link (2)