Generic function for loading a function from a DLL library

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
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;
functional-programming library delphi
 |Â
show 1 more comment
up vote
1
down vote
favorite
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;
functional-programming library delphi
What problem are you trying to solve by calling the functions this way?
â Dangph
Jun 13 at 7:58
@Dangph I would just like to have a generic function for loading functions from DLLs, that's all there is really.
â Vlastimil
Jun 13 at 8:29
It's just a programming exercise?
â Dangph
Jun 13 at 8:30
@Dangph No, it will be for some real use.
â Vlastimil
Jun 13 at 8:47
Why complicate things with dynamic loading?
â Dangph
Jun 13 at 10:24
 |Â
show 1 more comment
up vote
1
down vote
favorite
up vote
1
down vote
favorite
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;
functional-programming library delphi
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;
functional-programming library delphi
edited Jun 10 at 20:14
Jamalâ¦
30.1k11114225
30.1k11114225
asked Jun 10 at 9:08
Vlastimil
519316
519316
What problem are you trying to solve by calling the functions this way?
â Dangph
Jun 13 at 7:58
@Dangph I would just like to have a generic function for loading functions from DLLs, that's all there is really.
â Vlastimil
Jun 13 at 8:29
It's just a programming exercise?
â Dangph
Jun 13 at 8:30
@Dangph No, it will be for some real use.
â Vlastimil
Jun 13 at 8:47
Why complicate things with dynamic loading?
â Dangph
Jun 13 at 10:24
 |Â
show 1 more comment
What problem are you trying to solve by calling the functions this way?
â Dangph
Jun 13 at 7:58
@Dangph I would just like to have a generic function for loading functions from DLLs, that's all there is really.
â Vlastimil
Jun 13 at 8:29
It's just a programming exercise?
â Dangph
Jun 13 at 8:30
@Dangph No, it will be for some real use.
â Vlastimil
Jun 13 at 8:47
Why complicate things with dynamic loading?
â Dangph
Jun 13 at 10:24
What problem are you trying to solve by calling the functions this way?
â Dangph
Jun 13 at 7:58
What problem are you trying to solve by calling the functions this way?
â Dangph
Jun 13 at 7:58
@Dangph I would just like to have a generic function for loading functions from DLLs, that's all there is really.
â Vlastimil
Jun 13 at 8:29
@Dangph I would just like to have a generic function for loading functions from DLLs, that's all there is really.
â Vlastimil
Jun 13 at 8:29
It's just a programming exercise?
â Dangph
Jun 13 at 8:30
It's just a programming exercise?
â Dangph
Jun 13 at 8:30
@Dangph No, it will be for some real use.
â Vlastimil
Jun 13 at 8:47
@Dangph No, it will be for some real use.
â Vlastimil
Jun 13 at 8:47
Why complicate things with dynamic loading?
â Dangph
Jun 13 at 10:24
Why complicate things with dynamic loading?
â Dangph
Jun 13 at 10:24
 |Â
show 1 more comment
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
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.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
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.
add a comment |Â
up vote
1
down vote
accepted
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.
add a comment |Â
up vote
1
down vote
accepted
up vote
1
down vote
accepted
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.
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 at 21:53
W. Chang
1494
1494
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196221%2fgeneric-function-for-loading-a-function-from-a-dll-library%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
What problem are you trying to solve by calling the functions this way?
â Dangph
Jun 13 at 7:58
@Dangph I would just like to have a generic function for loading functions from DLLs, that's all there is really.
â Vlastimil
Jun 13 at 8:29
It's just a programming exercise?
â Dangph
Jun 13 at 8:30
@Dangph No, it will be for some real use.
â Vlastimil
Jun 13 at 8:47
Why complicate things with dynamic loading?
â Dangph
Jun 13 at 10:24