1
\$\begingroup\$

I am trying to write a generic function for loading a function from a DLL library. I am in no way an expert on DLLs, that is why I ask.

We have discussed it first in my Stack Overflow question to discover the most obvious errors, and there were some crucial ones.


Current version of my code follows:

function LoadFunctionFromLibrary(const LibraryName, FunctionName: string; out FunctionPointer: Pointer): Boolean;
var
 LibraryHandle: THandle;
begin
 Result := False;
 FunctionPointer := nil;
 LibraryHandle := Winapi.Windows.LoadLibrary(PChar(LibraryName));
 if LibraryHandle = 0 then Exit;
 FunctionPointer := Winapi.Windows.GetProcAddress(LibraryHandle, PChar(FunctionName));
 if Assigned(FunctionPointer) then
 Result := True;
end;

This version of the function has been successfully tested on my EnableInput function:

function EnableInput(const Enable: Boolean): Boolean;
var
 BlockInput: function(Block: BOOL): BOOL; stdcall;
begin
 Result := LoadFunctionFromLibrary('User32.dll', 'BlockInput', @BlockInput) and
 BlockInput(not Enable);
end;
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jun 10, 2018 at 9:08
\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

Just like Dangph, I wonder why you need this. There are other better approaches suggested in the previous comments.

Even if this is useful, Your solution is not great: 1. You repeatedly load the library and the function. 2. There is no way for you to free the loaded libraries.

Here is a better way to do it:

type
 TFunctionLoader = class
 private
 FLibraries: TStrings; // This stores the library handles and names
 FFunctions: TStrings; // This stores the function pointers and names
 public
 constructor Create;
 destructor Destroy; override;
 function LoadFunction(const LibraryName, FunctionName: string; 
 out FunctionPointer: Pointer): Boolean;
 end;
{ TFunctionLoader }
constructor TFunctionLoader.Create;
begin
 FLibraries := TStringList.Create;
 FFunctions := TStringList.Create;
end;
destructor TFunctionLoader.Destroy;
var
 i: Integer;
begin
 for i := 0 to FLibraries.Count - 1 do // free all opened libraries
 Windows.FreeLibrary(THandle(FLibraries.Objects[i]));
 FLibraries.Free; // free other objects
 FFunctions.Free;
end;
function TFunctionLoader.LoadFunction(const LibraryName, FunctionName: string;
 out FunctionPointer: Pointer): Boolean;
var
 i: Integer;
 LibraryHandle: THandle;
begin
 i := FFunctions.IndexOf(FunctionName); // Is the function already loaded?
 if i >= 0 then
 begin // Yes, just return the stored pointer
 FunctionPointer := Pointer(FFunctions.Objects[i]);
 Exit(True);
 end;
 i := FLibraries.IndexOf(LibraryName); // No, test if the library is already loaded
 if i < 0 then
 begin // No, load it and store in FLibraries
 LibraryHandle := Windows.LoadLibrary(PChar(LibraryName));
 if LibraryHandle = 0 then Exit(False); // Failed, quit
 i := FLibraries.AddObject(LibraryName, TObject(LibraryHandle));
 end;
 // Load the function from the library
 FunctionPointer := Windows.GetProcAddress(THandle(FLibraries.Objects[i]),
 PChar(FunctionName));
 Result := Assigned(FunctionPointer); // succeeded?
 if Result then // Add the function to FFunctions
 FFunctions.AddObject(FunctionName, TObject(FunctionPointer));
end;

With above you can define var FunctionLoader: TFunctionLoader; somewhere and add this to the end of the unit

initialization
 FunctionLoader := TFunctionLoader.Create;
finalization
 FunctionLoader.Free;
end.

Use it as

Result := FunctionLoader.LoadFunction('User32.dll', 'BlockInput', @BlockInput)
 and BlockInput(not Enable);

All functions and libraries will be loaded only once and will be automatically freed.

answered Jul 19, 2018 at 21:53
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.