📄 moduleloader.pas
字号:
end;
{$ENDIF MSWINDOWS}
{$IFDEF UNIX}
const
TYPE_E_ELEMENTNOTFOUND = $8002802B;
// load the .so file FileName
// the rules for FileName are those of dlopen()
// Returns: True = success, False = failure to load
// Assigns: the handle of the loaded .so to Module
// Warning: if Module has any other value than INVALID_MODULEHANDLE_VALUE
// on entry the function will do nothing but returning success.
function LoadModule(var Module: TModuleHandle; FileName: string): Boolean;
begin
if Module = INVALID_MODULEHANDLE_VALUE then
Module := dlopen(PChar(FileName), RTLD_NOW);
Result := Module <> INVALID_MODULEHANDLE_VALUE;
end;
// load the .so file FileName
// dlopen() with flags is used to get better control of the loading
// for the allowed values for flags see "man dlopen".
function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean;
begin
if Module = INVALID_MODULEHANDLE_VALUE then
Module := dlopen(PChar(FileName), Flags);
Result := Module <> INVALID_MODULEHANDLE_VALUE;
end;
// unload a .so loaded with LoadModule or LoadModuleEx
// The procedure will not try to unload a handle with
// value INVALID_MODULEHANDLE_VALUE and assigns this value
// to Module after unload.
procedure UnloadModule(var Module: TModuleHandle);
begin
if Module <> INVALID_MODULEHANDLE_VALUE then
dlclose(Module);
Module := INVALID_MODULEHANDLE_VALUE;
end;
// returns the pointer to the symbol named SymbolName
// if it is exported from the .so Module
// nil is returned if the symbol is not available
function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer;
begin
Result := nil;
if Module <> INVALID_MODULEHANDLE_VALUE then
Result := dlsym(Module, PChar(SymbolName));
end;
// returns the pointer to the symbol named SymbolName
// if it is exported from the .so Module
// nil is returned if the symbol is not available.
// as an extra the Boolean variable Accu is updated
// by anding in the success of the function.
// This is very handy for rendering a global result
// when accessing a long list of symbols.
function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer;
begin
Result := nil;
if Module <> INVALID_MODULEHANDLE_VALUE then
Result := dlsym(Module, PChar(SymbolName));
Accu := Accu and (Result <> nil);
end;
// get the value of variables exported from a .so Module
// Delphi cannot access variables in a .so directly, so
// this function allows to copy the data from the .so.
// Beware! You are accessing the .so memory image directly.
// Be sure to access a variable not a function and be sure
// to read the correct amount of data.
function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
var
Sym: Pointer;
begin
Result := True;
Sym := GetModuleSymbolEx(Module, SymbolName, Result);
if Result then
Move(Sym^, Buffer, Size);
end;
// set the value of variables exported from a .so Module
// Delphi cannot access variables in a .so directly, so
// this function allows to copy the data to the .so!
// BEWARE! You are accessing the .so memory image directly.
// Be sure to access a variable not a function and be sure
// to write the correct amount of data.
// The changes are not persistent. They get lost when the
// .so is unloaded.
function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
var
Sym: Pointer;
begin
Result := True;
Sym := GetModuleSymbolEx(Module, SymbolName, Result);
if Result then
Move(Buffer, Sym^, Size);
end;
{$ENDIF UNIX}
//=== { TModuleLoader } ======================================================
constructor TModuleLoader.Create(const ADLLName: string; LoadMethods: TModuleLoadMethods = []);
begin
inherited Create;
FHandle := INVALID_MODULEHANDLE_VALUE;
FDLLName := ADLLName;
Load(LoadMethods);
end;
destructor TModuleLoader.Destroy;
begin
Unload;
inherited Destroy;
end;
procedure TModuleLoader.Error(ErrorCode: Cardinal);
begin
// overriden classes should handle this
end;
function TModuleLoader.GetExportedSymbol(const AName: string; var Buffer;
Size: Integer): Boolean;
var
ASymbol: Pointer;
begin
Result := GetProcedure(AName, ASymbol);
if Result then
Move(ASymbol^, Buffer, Size);
end;
function TModuleLoader.GetLoaded: Boolean;
begin
Result := Handle <> INVALID_MODULEHANDLE_VALUE;
end;
function TModuleLoader.GetProcedure(const AName: string; var AProc: Pointer): Boolean;
begin
Result := Loaded;
if Result and not Assigned(AProc) then
begin
AProc := GetModuleSymbol(Handle, AName);
Result := Assigned(AProc);
end;
if not Result then
begin
AProc := nil;
Error(DWORD(TYPE_E_ELEMENTNOTFOUND));
end;
end;
class function TModuleLoader.IsAvaliable(const ADLLName: string; const AProcName: string = ''): Boolean;
var
Module: TModuleHandle;
P: Pointer;
begin
Result := LoadModule(Module, ADLLName);
if Result then
begin
if AProcName <> '' then
begin
P := GetModuleSymbol(Module, AProcName);
Result := Assigned(P);
end;
UnloadModule(Module);
end;
end;
procedure TModuleLoader.Load(LoadMethods: TModuleLoadMethods);
const
cLoadMethods: array [TModuleLoadMethod] of DWORD =
{$IFDEF MSWINDOWS}
(DONT_RESOLVE_DLL_REFERENCES, LOAD_LIBRARY_AS_DATAFILE, LOAD_WITH_ALTERED_SEARCH_PATH);
{$ENDIF MSWINDOWS}
{$IFDEF UNIX}
(RTLD_LAZY, RTLD_LAZY, RTLD_LAZY); // there is not really a equivalent under Linux
{$ENDIF UNIX}
var
Flags: DWORD;
I: TModuleLoadMethod;
begin
Flags := 0;
for I := Low(TModuleLoadMethod) to High(TModuleLoadMethod) do
if I in LoadMethods then
Flags := Flags or cLoadMethods[I];
if FHandle = INVALID_MODULEHANDLE_VALUE then
LoadModuleEx(FHandle, DLLName, Flags);
if FHandle = INVALID_MODULEHANDLE_VALUE then
Error(GetLastError);
end;
function TModuleLoader.SetExportedSymbol(const AName: string; var Buffer;
Size: Integer): Boolean;
var
ASymbol: Pointer;
begin
Result := GetProcedure(AName, ASymbol);
if Result then
Move(Buffer, ASymbol^, Size);
end;
procedure TModuleLoader.Unload;
begin
if FHandle <> INVALID_MODULEHANDLE_VALUE then
UnloadModule(FHandle);
FHandle := INVALID_MODULEHANDLE_VALUE;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -