Request
Can I import abstract classes?Solution
Yes. The following demo illustrates it.Script:{$APPTYPE CONSOLE} program Project1; uses PaxCompiler, PaxInterpreter, PaxRegister; type TMyHostClass = class public constructor Create; virtual; abstract; procedure P; virtual; abstract; end; TMyHostClassClass = class of TMyHostClass; var PaxCompiler1: TPaxCompiler; PaxInterpreter1: TPaxInterpreter; PaxPascalLanguage1: TPaxPascalLanguage; I: Integer; C: TMyHostClassClass; X: TMyHostClass; begin I := RegisterClassType(0, TMyHostClass); // Note, you have to register abstract members in order of appearance in the class definition above. RegisterHeader(I, 'constructor Create; virtual; abstract;', nil); RegisterHeader(I, 'procedure P; virtual; abstract;', nil); PaxCompiler1 := TPaxCompiler.Create(nil); PaxInterpreter1 := TPaxInterpreter.Create(nil); PaxPascalLanguage1 := TPaxPascalLanguage.Create(nil); try PaxCompiler1.RegisterLanguage(PaxPascalLanguage1); PaxCompiler1.AddModule('1', 'Pascal'); PaxCompiler1.AddCodeFromFile('1', 'script.txt'); if PaxCompiler1.Compile(PaxInterpreter1) then begin PaxInterpreter1.RunInitialization; // Create script-defined object at host side. C := TMyHostClassClass(PaxInterpreter1.GetAddress('TMyScriptClass')^); X := C.Create; X.P; X.Free; end else begin writeln(PaxCompiler1.ErrorMessage[0]); writeln(PaxCompiler1.ErrorLineNumber[0]); writeln(PaxCompiler1.ErrorLine[0]); end; for I:=0 to PaxCompiler1.WarningCount - 1 do begin writeln(PaxCompiler1.WarningMessage[I]); writeln(PaxCompiler1.WarningLineNumber[I]); writeln(PaxCompiler1.WarningLine[I]); end; finally PaxCompiler1.Free; PaxInterpreter1.Free; PaxPascalLanguage1.Free; end; writeln('Press any key...'); Readln; end.type TMyScriptClass = class(TMyHostClass) constructor Create; override; procedure P; override; end; constructor TMyScriptClass.Create; begin print 'Script object of ' + ClassName + ' is created.'; end; procedure TMyScriptClass.P; begin print 'Hello from script!'; end; begin end.2
Request
How I could register an overloadesd procedure/function for scripting engine?Solution
You need to find out address of the procedure (function). It is more easy to explain it on an example. Let's suppose we have 2 overloaded procedures:You can use the following code to obtain the addresses:procedure MyProc(const S: String); overload; begin writeln(1); end; procedure MyProc(I : Integer); overload; begin writeln(2); end;function Address1: Pointer; type TMyProc = procedure (const S: String); var P: TMyProc; begin P := MyProc; Move(P, result, 4); end; function Address2: Pointer; type TMyProc = procedure (I: Integer); var P: TMyProc; begin P := MyProc; Move(P, result, 4); end;
Now you can register the overloaded procedures for paxCompiler engine:
RegisterHeader(0, 'procedure MyProc(const S: String); overload;', Address1); RegisterHeader(0, 'procedure MyProc(I : Integer); overload;', Address2);
Request
How I could register an overloadesd method for scripting engine? In particular, how I could register an overloaded virtual method?Solution
Let's suppose we have a class:You can use the following code to obtain the addresses of methods:type TMyClass = class procedure MyProc(const S: String); overload; virtual; procedure MyProc(I : Integer); overload; virtual; end;After optimization, we can get improved versions of the address functions:function MethodAddress1: Pointer; type TMyProc = procedure (const S: String) of object; var P: TMyProc; X: TMyClass; M: TMethod; begin GetMem(Pointer(X), 4); Pointer(Pointer(X)^) := TMyClass; P := X.MyProc; Move(P, M, SizeOf(TMethod)); result := M.Code; FreeMem(Pointer(X), 4); end; function MethodAddress2: Pointer; type TMyProc = procedure (I: Integer) of object; var P: TMyProc; X: TMyClass; M: TMethod; begin GetMem(Pointer(X), 4); Pointer(Pointer(X)^) := TMyClass; P := X.MyProc; Move(P, M, SizeOf(TMethod)); result := M.Code; FreeMem(Pointer(X), 4); end;Now we can registerTMyClass type for paxCompiler:function MethodAddress1_Op: Pointer; type TMyProc = procedure (const S: String) of object; var P: TMyProc; X: TMyClass; M: TMethod; V: TClass; begin V := TMyClass; X := @V; P := X.MyProc; Move(P, M, SizeOf(TMethod)); result := M.Code; end; function MethodAddress2_Op: Pointer; type TMyProc = procedure (I: Integer) of object; var P: TMyProc; X: TMyClass; M: TMethod; V: TClass; begin V := TMyClass; X := @V; P := X.MyProc; Move(P, M, SizeOf(TMethod)); result := M.Code; end;G := RegisterClassType(0, TMyClass); RegisterHeader(G, 'procedure MyProc(const S: String); overload; virtual;', MethodAddress1_Op); RegisterHeader(G, 'procedure MyProc(I : Integer); overload; virtual;', MethodAddress2_Op);
Request
How I could register an overloadesd constructor for scripting engine?Solution
Let's suppose weI have a host class:Thentype TMyClass = class constructor Create; overload; constructor Create(I: Integer); overload; virtual; end;returns address of the first overloaded constructor. To find address of the second constructor we create an inherited classP := @TMyClass.Create;ThenTMyClass2 = class(TMyClass) constructor Create(I: Integer); override; end;returns address of non-overloaded constructor of this class. After that we apply 2 functions:P := @TMyClass2.Create;to find address of the second constructor of TMyClass:const MaxVirtuals = 1000; type PPointerArray = ^TPointerArray; TPointerArray = array[0..MaxVirtuals] of pointer; function GetMethodIndex(C: TClass; Address: Pointer): Integer; var I: Integer; begin result := -1; for I := 0 to MaxVirtuals do if PPointerArray(C)[I] = Address then begin result := I; Exit; end; end; function GetMethodAddress(C: TClass; Index: Integer): Pointer; begin result := PPointerArray(C)[Index]; end;I := GetMethodIndex(TMyClass2, P); P := GetMethodAddress(TMyClass, I);
Copyright © 2006-2014 VIRT Laboratory. All rights reserved.