{ Compiletime DLL importing support } unit uPSC_dll; {$I PascalScript.inc} interface { Function FindWindow(c1, c2: PChar): Cardinal; external 'FindWindow@user32.dll stdcall'; } uses uPSCompiler, uPSUtils; {$IFDEF DELPHI3UP } resourceString {$ELSE } const {$ENDIF } RPS_Invalid_External = 'Invalid External'; RPS_InvalidCallingConvention = 'Invalid Calling Convention'; function DllExternalProc(Sender: TPSPascalCompiler; Decl: TPSParametersDecl; const OriginalName, FExternal: tbtstring): TPSRegProc; type TDllCallingConvention = (clRegister , clPascal , ClCdecl , ClStdCall ); var DefaultCC: TDllCallingConvention; procedure RegisterDll_Compiletime(cs: TPSPascalCompiler); implementation function rpos(ch: tbtchar; const s: tbtstring): Longint; var i: Longint; begin for i := length(s) downto 1 do if s[i] = ch then begin Result := i; exit; end; result := 0; end; function RemoveQuotes(s: tbtstring): tbtstring; begin result := s; if result = '' then exit; if Result[1] = '"' then delete(result ,1,1); if (Result <> '') and (Result[Length(result)] = '"') then delete(result, length(result), 1); end; function DllExternalProc(Sender: TPSPascalCompiler; Decl: TPSParametersDecl; const OriginalName, FExternal: tbtstring): TPSRegProc; var FuncName, Name, FuncCC, s, s2: AnsiString; CC: TDllCallingConvention; DelayLoad, LoadWithAlteredSearchPath: Boolean; begin Name := FastUpperCase(OriginalName); DelayLoad := False; LoadWithAlteredSearchPath := false; FuncCC := FExternal; if (pos(tbtChar('@'), FuncCC) = 0) then begin Sender.MakeError('', ecCustomError, tbtString(RPS_Invalid_External)); Result := nil; exit; end; FuncName := copy(FuncCC, 1, rpos('@', FuncCC)-1)+#0; delete(FuncCc, 1, length(FuncName)); if pos(tbtchar(' '), Funccc) <> 0 then begin if FuncCC[1] = '"' then begin Delete(FuncCC, 1, 1); FuncName := RemoveQuotes(copy(FuncCC, 1, pos(tbtchar('"'), FuncCC)-1))+#0+FuncName; Delete(FuncCC,1, pos(tbtchar('"'), FuncCC)); if (FuncCC <> '') and( FuncCC[1] = ' ') then delete(FuncCC,1,1); end else begin FuncName := copy(FuncCc, 1, pos(tbtchar(' '),FuncCC)-1)+#0+FuncName; Delete(FuncCC, 1, pos(tbtchar(' '), FuncCC)); end; if pos(tbtchar(' '), FuncCC) > 0 then begin s := Copy(FuncCC, pos(tbtchar(' '), Funccc)+1, MaxInt); FuncCC := FastUpperCase(Copy(FuncCC, 1, pos(tbtchar(' '), FuncCC)-1)); Delete(FuncCC, pos(tbtchar(' '), Funccc), MaxInt); repeat if pos(tbtchar(' '), s) > 0 then begin s2 := Copy(s, 1, pos(tbtchar(' '), s)-1); delete(s, 1, pos(tbtchar(' '), s)); end else begin s2 := s; s := ''; end; if FastUppercase(s2) = 'DELAYLOAD' then DelayLoad := True {$IFNDEF LINUX} else if FastUppercase(s2) = 'LOADWITHALTEREDSEARCHPATH' then LoadWithAlteredSearchPath := True {$ENDIF} else begin Sender.MakeError('', ecCustomError, 'Invalid External'); Result := nil; exit; end; until s = ''; end else FuncCC := FastUpperCase(FuncCC); if FuncCC = 'STDCALL' then cc := ClStdCall else if FuncCC = 'CDECL' then cc := ClCdecl else if FuncCC = 'REGISTER' then cc := clRegister else if FuncCC = 'PASCAL' then cc := clPascal else begin Sender.MakeError('', ecCustomError, tbtstring(RPS_InvalidCallingConvention)); Result := nil; exit; end; end else begin FuncName := RemoveQuotes(FuncCC)+#0+FuncName; FuncCC := ''; cc := DefaultCC; end; FuncName := 'dll:'+FuncName+tbtchar(cc)+tbtchar(bytebool(DelayLoad)) +tbtchar(bytebool(LoadWithAlteredSearchPath))+ declToBits(Decl); Result := TPSRegProc.Create; Result.ImportDecl := FuncName; Result.Decl.Assign(Decl); Result.Name := Name; Result.OrgName := OriginalName; Result.ExportName := False; end; procedure RegisterDll_Compiletime(cs: TPSPascalCompiler); begin cs.OnExternalProc := DllExternalProc; cs.AddFunction('procedure UnloadDll(s: string)'); cs.AddFunction('function DLLGetLastError: Longint'); end; begin DefaultCc := clRegister; end.