⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 moduleloader.pas

📁 human interface devices.zip 一套组件
💻 PAS
📖 第 1 页 / 共 2 页
字号:
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 + -