home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / kompon / d23456 / CAJSCRTP.ZIP / libraries / call / ifpsdll.pas < prev    next >
Pascal/Delphi Source File  |  2001-10-03  |  5KB  |  207 lines

  1. unit ifpsdll;
  2. {
  3.   Innerfuse Pascal Script DLL Library
  4.   For license see Innerfuse Pascal Script license file
  5.  
  6.   This unit and all parts of it may only be used with Innerfuse Pascal
  7.   Script.
  8.  
  9.   Does not work in attached units.
  10. }
  11. {$I ifs_def.inc}
  12. interface
  13. uses
  14.   ifpscall, ifspas, ifs_var, ifs_utl, {$IFDEF LINUX}libc{$ELSE}Windows{$ENDIF};
  15.  
  16. {
  17.   Defines for this unit:
  18.     DEFCCPPASCAL - Set default calling convention to Pascal.
  19.     DEFCCCDECL - Set default calling convention to Cdecl.
  20.     DEFCCSTDCALL - Set default calling convention to StdCall.
  21.     Else the default Calling Convention is Register.
  22. }
  23.  
  24. procedure RegisterDllCallLibrary(Sender: TIFPasScript);
  25. {
  26. Adds:
  27.  
  28.   function LoadLibrary(Name: string; var Res: ResourcePointer): Boolean;
  29.   procedure CloseLibrary(Res: ResourcePointer);
  30.   function MapLibraryProc(RealProcName, Declaration: string): Boolean;
  31.  
  32. Valid types for in Declaration:
  33. Boolean,
  34. WordBool,
  35. LongBool,
  36. Byte
  37. Shortint
  38. Word
  39. Smallint
  40. Longint
  41. Integer
  42. Cardinal
  43. PChar (string with EXT param of TypeRec to 1) (*)
  44. String
  45.  
  46. Valid calling conventions:
  47. register (default)
  48. stdcall
  49. cdecl
  50. pascal
  51.  
  52. Pchar type does not support Var parameter.
  53. }
  54.  
  55. implementation
  56. const
  57.   DefaultCallingConvention: TCallingConvention =
  58.   {$IFDEF DEFCCPPASCAL}ccPascal;{$ELSE}
  59.   {$IFDEF DEFCCCDECL}ccCdecl;{$ELSE}
  60.   {$IFDEF DEFCCSTDCALL}ccStdcall;{$ELSE}
  61.   ccRegister;
  62.   {$ENDIF}
  63.   {$ENDIF}
  64.   {$ENDIF}
  65.  
  66.  
  67. type
  68.   PCreatedDll = ^TCreatedDll;
  69.   TCreatedDll = record
  70.     AlreadyFreed: Boolean;
  71.     {$IFDEF LINUX}
  72.     Dll: Pointer;
  73.     {$ELSE}
  74.     Dll: THandle;
  75.     {$ENDIF}
  76.     Calls: TIFList;  { Contains PProcedure pointers. PProcedure()^.Ext contains a pointer to the procedure. }
  77.   end;
  78.  
  79. procedure FreeProc(id: Pointer; Data: PCreatedDll);
  80. begin
  81.   if not data.AlreadyFreed then
  82.   begin
  83.     Data^.Calls.Free;
  84.     {$IFDEF LINUX}
  85.     dlclose(Data^.Dll);
  86.     {$ELSE}
  87.     FreeLibrary(Data^.Dll);
  88.     {$ENDIF}
  89.   end;
  90.   Dispose(Data);
  91. end;
  92.  
  93. function DProc(Sender: TIFPasScript; ScriptID: Pointer; Proc: PProcedure; Params: PVariableManager; res: PIfVariant): TIfPasScriptError;
  94. begin
  95.   if not InnerfuseCall(Sender, Nil, PProcedure(Proc)^._Ext, TCallingConvention(PProcedure(Proc)^._Ext2), Params, Res) then
  96.   begin
  97.     Sender.RunError2(Sender, ECustomError, 'Could not call function');
  98.     DProc := ECustomError;
  99.   end else
  100.     DPRoc := ENoError;
  101. end;
  102.  
  103.  
  104.  
  105. function MProc(Sender: TIFPasScript; ScriptID: Pointer; Proc: PProcedure; Params: PVariableManager; res: PIfVariant): TIfPasScriptError;
  106. var
  107.   n: PCreatedDll;
  108.   p: PProcedure;
  109.   I: Longint;
  110.   procedure F1;
  111.   var
  112.     FuncName, FuncParam: String;
  113.     CC: TCallingConvention;
  114.     u: Pointer;
  115.   begin
  116.     if ReadHeader(Sender, GetString(VM_Get(Params, 2)), FuncName, FuncParam, CC, DefaultCallingConvention) then
  117.     begin
  118.       {$IFDEF LINUX}
  119.       u := dlsym(n^.Dll, PChar(GetString(VM_Get(Params, 1))));
  120.       {$ELSE}
  121.       u := GetProcAddress(n^.Dll, PChar(GetString(VM_Get(Params, 1))));
  122.       {$ENDIF}
  123.       if u <> nil then
  124.       begin
  125.         u := Sender.AddFunction(@DProc, 'procedure '+FuncName+';', U);
  126.         n^.calls.Add(U);
  127.         PProcedure(U)^.Decl := FuncParam;
  128.         PProcedure(U)^._Ext2 := Pointer(Byte(CC));
  129.         SetBoolean(Res, True);
  130.       end else
  131.         SetBoolean(Res, False);
  132.     end else
  133.       SetBoolean(Res, False);
  134.   end;
  135. begin
  136.   MProc := ENoError;
  137.   if Proc^.Name = 'LOADLIBRARY' then
  138.   begin
  139.     New(N);
  140.     {$IFDEF LINUX}
  141.     N^.Dll := dlopen(PChar(GetString(VM_Get(Params, 0))), RTLD_LAZY);
  142.     {$ELSE}
  143.     N^.Dll := LoadLibrary(PChar(GetString(VM_Get(Params, 0))));
  144.     {$ENDIF}
  145.     if N^.Dll = {$IFDEF LINUX}nil{$ELSE}0{$ENDIF} then
  146.     begin
  147.       Dispose(N);
  148.       SetBoolean(Res, False);
  149.     end else begin
  150.       N^.AlreadyFreed := False;
  151.       N^.Calls := TIFList.Create;
  152.       GetVarLink(VM_Get(Params, 1))^.Cv_Int1 := N;
  153.       GetVarLink(VM_Get(Params, 1))^.CV_Int2 := @MProc;
  154.       SetBoolean(Res, True);
  155.       Sender.AddResource(@FreeProc, N);
  156.     end;
  157.   end else if Proc^.Name = 'CLOSELIBRARY' then
  158.   begin
  159.     if GetVarLink(VM_Get(Params, 0))^.CV_Int2 <> @MProc then
  160.     begin
  161.       MPRoc := ETypeMismatch;
  162.       exit;
  163.     end;
  164.     n := GetVarLink(VM_Get(Params, 0))^.CV_Int1;
  165.     if n^.AlreadyFreed then
  166.     begin
  167.       MProc := ETypeMismatch;
  168.       exit;
  169.     end;
  170.     for i := 0 to Longint(n^.Calls.Count) -1 do
  171.     begin
  172.       Sender.RemoveFunction(n^.Calls.GetItem(I));
  173.       p := N^.Calls.GetItem(I);
  174.       Dispose(P);
  175.     end;
  176.     {$IFDEF LINUX}
  177.     dlclose(N^.Dll);
  178.     {$ELSE}
  179.     FreeLibrary(N^.DLL);
  180.     {$ENDIF}
  181.     N^.AlreadyFreed := True;
  182.   end else if Proc^.Name = 'MAPLIBRARYPROC' then
  183.   begin
  184.     if GetVarLink(VM_Get(Params, 0))^.CV_Int2 <> @MProc then
  185.     begin
  186.       MPRoc := ETypeMismatch;
  187.       exit;
  188.     end;
  189.     n := GetVarLink(VM_Get(Params, 0))^.CV_Int1;
  190.     if n^.AlreadyFreed then
  191.     begin
  192.       MProc := ETypeMismatch;
  193.       exit;
  194.     end;
  195.     F1;
  196.   end;
  197. end;
  198.  
  199. procedure RegisterDllCallLibrary(Sender: TIFPasScript);
  200. begin
  201.   Sender.AddFunction(@MProc, 'function LoadLibrary(Name: string; var Res: ResourcePointer): Boolean;', nil);
  202.   Sender.AddFunction(@MProc, 'procedure CloseLibrary(Res: ResourcePointer);', nil);
  203.   Sender.AddFunction(@MProc, 'function MapLibraryProc(Res: ResourcePointer; DllProcName, Declaration: string): Boolean;', nil);
  204. end;
  205.  
  206. end.
  207.