git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@35 05c56307-c608-d34a-929d-697000501d7a
159 lines
3.5 KiB
ObjectPascal
159 lines
3.5 KiB
ObjectPascal
unit ifpidll2runtime;
|
|
|
|
{$I ifps3_def.inc}
|
|
interface
|
|
uses
|
|
ifpicall, ifps3, ifps3utl, ifps3common;
|
|
{Register the dll runtime library}
|
|
procedure RegisterDLLRuntime(Caller: TIFPSExec);
|
|
{Process a dll import (no need to call this function)}
|
|
function ProcessDllImport(Caller: TIFPSExec; P: PIFProcRec): Boolean;
|
|
|
|
implementation
|
|
uses
|
|
{$IFDEF LINUX}
|
|
LibC;
|
|
{$ELSE}
|
|
Windows;
|
|
{$ENDIF}
|
|
|
|
{
|
|
p^.Ext1 contains the pointer to the Proc function
|
|
p^.ExportDecl:
|
|
'dll:'+DllName+#0+FunctionName+#0+chr(Cc)+VarParams
|
|
}
|
|
|
|
type
|
|
PLoadedDll = ^TLoadedDll;
|
|
TLoadedDll = record
|
|
dllnamehash: Longint;
|
|
dllname: string;
|
|
{$IFDEF LINUX}
|
|
dllhandle: Pointer;
|
|
{$ELSE}
|
|
dllhandle: THandle;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
|
|
procedure DllFree(Sender: TIFPSExec; P: PLoadedDll);
|
|
begin
|
|
{$IFDEF LINUX}
|
|
dlclose(p^.dllhandle);
|
|
{$ELSE}
|
|
FreeLibrary(p^.dllhandle);
|
|
{$ENDIF}
|
|
Dispose(p);
|
|
end;
|
|
|
|
|
|
|
|
function DllProc(Caller: TIFPSExec; p: PIFProcRec; Global, Stack: TIfList): Boolean;
|
|
|
|
var
|
|
i: Integer;
|
|
MyList: TIfList;
|
|
n: PIFVariant;
|
|
CurrStack: Cardinal;
|
|
cc: TCallingConvention;
|
|
s: string;
|
|
begin
|
|
s := p^.ExportDecl;
|
|
delete(S, 1, pos(#0, s));
|
|
delete(S, 1, pos(#0, s));
|
|
if length(S) < 2 then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
cc := TCallingConvention(s[1]);
|
|
delete(s, 1, 1);
|
|
CurrStack := Stack.Count - Cardinal(length(s));
|
|
if s[1] = #0 then inc(CurrStack);
|
|
MyList := tIfList.Create;
|
|
for i := 2 to length(s) do
|
|
begin
|
|
MyList.Add(nil);
|
|
end;
|
|
for i := length(s) downto 2 do
|
|
begin
|
|
n :=rp(Stack.GetItem(CurrStack));
|
|
if s[i] <> #0 then
|
|
begin
|
|
n^.RefCount := n^.RefCount or IFPSAddrStackStart;
|
|
end;
|
|
MyList.SetItem(i - 2, n);
|
|
inc(CurrStack);
|
|
end;
|
|
try
|
|
if s[1] <> #0 then
|
|
begin
|
|
n := rp(Stack.GetItem(CurrStack));
|
|
end else n := nil;
|
|
InnerfuseCall(Caller, nil, p^.Ext1, cc, MyList, n, nil);
|
|
result := true;
|
|
except
|
|
result := false;
|
|
end;
|
|
MyList.Free;
|
|
end;
|
|
|
|
function ProcessDllImport(Caller: TIFPSExec; P: PIFProcRec): Boolean;
|
|
var
|
|
s, s2: string;
|
|
h, i: Longint;
|
|
ph: PLoadedDll;
|
|
{$IFDEF LINUX}
|
|
dllhandle: Pointer;
|
|
{$ELSE}
|
|
dllhandle: THandle;
|
|
{$ENDIF}
|
|
begin
|
|
s := p^.ExportDecl;
|
|
Delete(s, 1, 4);
|
|
s2 := copy(s, 1, pos(#0, s)-1);
|
|
delete(s, 1, length(s2)+1);
|
|
h := makehash(s2);
|
|
i := 2147483647; // maxint
|
|
dllhandle := 0;
|
|
repeat
|
|
ph := Caller.FindProcResource2(@dllFree, i);
|
|
if i = -1 then
|
|
begin
|
|
{$IFDEF LINUX}
|
|
dllhandle := dlopen(PChar(s2), RTLD_LAZY);
|
|
{$ELSE}
|
|
dllhandle := LoadLibrary(Pchar(s2));
|
|
{$ENDIF}
|
|
if dllhandle = {$IFDEF LINUX}nil{$ELSE}0{$ENDIF}then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
new(ph);
|
|
ph^.dllnamehash := h;
|
|
ph^.dllname := s2;
|
|
ph^.dllhandle := dllhandle;
|
|
Caller.AddResource(@DllFree, ph);
|
|
end;
|
|
if (ph^.dllnamehash = h) and (ph^.dllname = s2) then
|
|
begin
|
|
dllhandle := ph^.dllhandle;
|
|
end;
|
|
dec(i);
|
|
until dllhandle <> {$IFDEF LINUX}nil{$ELSE}0{$ENDIF};
|
|
{$IFDEF LINUX}
|
|
p^.Ext1 := dlsym(dllhandle, pchar(copy(s, 1, pos(#0, s)-1)));
|
|
{$ELSE}
|
|
p^.Ext1 := GetProcAddress(dllhandle, pchar(copy(s, 1, pos(#0, s)-1)));
|
|
{$ENDIF}
|
|
p^.ProcPtr := DllProc;
|
|
Result := p^.Ext1 <> nil;
|
|
end;
|
|
|
|
procedure RegisterDLLRuntime(Caller: TIFPSExec);
|
|
begin
|
|
Caller.AddSpecialProcImport('dll', @ProcessDllImport, nil);
|
|
end;
|
|
end.
|