Generic function for loading a function from a DLL library

The name of the pictureThe name of the pictureThe name of the pictureClash 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;






share|improve this question





















  • 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
















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;






share|improve this question





















  • 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












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;






share|improve this question













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;








share|improve this question












share|improve this question




share|improve this question








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
















  • 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










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.






share|improve this answer





















    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    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






























    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.






    share|improve this answer

























      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.






      share|improve this answer























        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.






        share|improve this answer













        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.







        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered Jul 19 at 21:53









        W. Chang

        1494




        1494






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            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













































































            Popular posts from this blog

            Python Lists

            Aion

            JavaScript Array Iteration Methods