How to call a C function (in the host process) from a DLL
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10

Thread: How to call a C function (in the host process) from a DLL

  1. #1
    Join Date
    Jul 2013
    Posts
    4

    How to call a C function (in the host process) from a DLL

    Hi all
    I have a main program that loads a dll and calls functions inside dll. Everything is fine.
    Now I would like to call a function belonging to the main exe from the dll. I didi this:

    main.c:
    __declspec(dllexport) void HelloWorld(void)
    {
    printf("The function was called by dll! \n");
    }

    On dll, .cpp file, on top:
    __declspec(dllimport) void HelloWorld(void);


    On a dll method which is called from EXE I call:

    int DLL_EXPORT Finalize(void)
    {
    exitCondition=0;
    printf("Thread was killed\n");

    HelloWorld();

    return 0;
    }


    but compiler says:

    ...\main.cpp|59|undefined reference to `_imp___Z8HelloWorldv'|


    How to solve this?

    Thanks a lot

    Alex

  2. #2
    Join Date
    Apr 1999
    Posts
    27,427

    Re: How to call a C function (in the host process) from a DLL

    Quote Originally Posted by alexe100 View Post
    Hi all
    I have a main program that loads a dll and calls functions inside dll. Everything is fine.
    Now I would like to call a function belonging to the main exe from the dll. I didi this:
    Is that a linker or a compiler error? If it is a linker error, nowhere do you show how you link the modules. Where is your import library and how is it specified in the build process?
    I have a main program that loads a dll
    You also didn't mention how this DLL is loaded. Implicitly? Using LoadLibrary()?

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Jul 2013
    Posts
    4

    Re: How to call a C function (in the host process) from a DLL

    The main program is called test1. The dll is called DLLTEST. These are two projects created using codeblocks and mingw.

    On main function of test1 I do:

    hDLL = LoadLibrary("DLLTESTE.dll");
    lpfnDllFunc1= (...) GetProcAddress(...)
    ret=lpfnDllFunc1(30); //And i call the func1 using arg 30

    Everything is fine here!


    Now I would like to call dll Func1 as I do, but then the Func1 calls HelloWorld in the test1 executable, like a loop, process calls in dll and dll calls in process.

    It is a link error!

    Alex

    Alex

  4. #4
    Join Date
    Apr 1999
    Posts
    27,427

    Re: How to call a C function (in the host process) from a DLL

    Quote Originally Posted by alexe100 View Post
    The main program is called test1. The dll is called DLLTEST. These are two projects created using codeblocks and mingw.
    If you're using LoadLibrary, why are you trying to link to an exported function name?? There is no need to link anything if you're using LoadLibrary.

    Look here:
    Code:
    #include <windows.h>
    #include <iostream>
    
    int main()
    {
        HMODULE hMod = LoadLibrary("mydll.dll");
        if ( hMod && GetProcAddress(hMod, "MyFunctionName") != NULL )
             std::cout << "The function MyFunctionName was found";
        if ( hMod )
             FreeLibrary( hMod );
    }
    There is no need to link anything from mydll. The function pointer is returned by GetProcAddress() at runtime, so trying to find the function at link time makes no sense whatsoever. What you need to do is probably remove all of your user-defined import libraries from your linker options. You don't need them if you're using LoadLibrary.

    The only thing you need to make sure is that the "HelloWorld" function is exported, so that GetProcAddress() can find it when you call LoadLibrary on the module that contains HelloWorld.

    In other words, you don't need any of this in the code where you want to call this function:
    Code:
    main.c:
    On dll, .cpp file, on top:
    __declspec(dllimport) void HelloWorld(void);
    There is no "HelloWorld" function that lives in the executable you want to call it from. You have LoadLibrary, GetProcAddress, and a function pointer returned by GetProcAddress that points to an exported function. Nothing else. So trying to write a prototype for HelloWorld and including the prototype is a waste of time if that function is not there.

    Within the module that defines HelloWorld(), then yes, you would build the module with the prototype, just like any other C/C++ module. But from the module you are calling HelloWorkd from using GetProcAddress(), you should not be prototyping HelloWorld() function, because that function doesn't exist at link time anywhere, as it will be "retrieved" at runtime using GetProcAddress.

    What you want to do is define a function pointer that is compatible with the one returned by GetProcAddress.
    Code:
    typedef void (*HelloWorldFn)();
    //...
    HelloWorldFn fn = (HelloWorldFn)GetProcAddress(hMod, "HelloWorld");
    if ( fn )
       fn();  // call the HelloWorld function
    Something like this.

    Also, I believe you should use GetModuleHandle() from the DLL, so that you get the HMODULE of the executable that is running. It serves the same purpose as LoadLibrary() without having to go through the DllMain() and other initializations that LoadLibrary() will do.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 25th, 2013 at 02:57 PM.

  5. #5
    Join Date
    Jul 2013
    Posts
    4

    Re: How to call a C function (in the host process) from a DLL

    I am sorry, but you did not understood my problem!

    HelloWorld function does not belongs to dll! It belongs to the process!

    Look:

    test1.exe has the following functions:

    main()

    helloWorld()

    TESTDLL.DLL has the followinf functions:
    Func1()


    I want to call Func1 from main (using loadlibrary) but when Func1 is invoked, Func1() must invoke helloworld()!

    Main() ---> Func1()---->HelloWorld (in one shot!)


    Till now, I can call Func1() from main() without problems! My problem is call helloworld from Func1 when Func1 is called by main.



    In a simpler view, my problem is: is it possible to call a method in the host .exe from the hosted DLL? IF so, how?

    Thanks a lot

    Alex








    Quote Originally Posted by Paul McKenzie View Post
    If you're using LoadLibrary, why are you trying to link to an exported function name?? There is no need to link anything if you're using LoadLibrary.

    Look here:
    Code:
    #include <windows.h>
    #include <iostream>
    
    int main()
    {
        HMODULE hMod = LoadLibrary("mydll.dll");
        if ( hMod && GetProcAddress(hMod, "MyFunctionName") != NULL )
             std::cout << "The function MyFunctionName was found";
        if ( hMod )
             FreeLibrary( hMod );
    }
    There is no need to link anything from mydll. The function pointer is returned by GetProcAddress() at runtime, so trying to find the function at link time makes no sense whatsoever. What you need to do is probably remove all of your user-defined import libraries from your linker options. You don't need them if you're using LoadLibrary.

    The only thing you need to make sure is that the "HelloWorld" function is exported, so that GetProcAddress() can find it when you call LoadLibrary on the module that contains HelloWorld.

    In other words, you don't need any of this in the code where you want to call this function:
    Code:
    main.c:
    On dll, .cpp file, on top:
    __declspec(dllimport) void HelloWorld(void);
    There is no "HelloWorld" function that lives in the executable you want to call it from. You have LoadLibrary, GetProcAddress, and a function pointer returned by GetProcAddress that points to an exported function. Nothing else. So trying to write a prototype for HelloWorld and including the prototype is a waste of time if that function is not there.

    Within the module that defines HelloWorld(), then yes, you would build the module with the prototype, just like any other C/C++ module. But from the module you are calling HelloWorkd from using GetProcAddress(), you should not be prototyping HelloWorld() function, because that function doesn't exist at link time anywhere, as it will be "retrieved" at runtime using GetProcAddress.

    What you want to do is define a function pointer that is compatible with the one returned by GetProcAddress.
    Code:
    typedef void (*HelloWorldFn)();
    //...
    HelloWorldFn fn = (HelloWorldFn)GetProcAddress(hMod, "HelloWorld");
    if ( fn )
       fn();  // call the HelloWorld function
    Something like this.

    Also, I believe you should use GetModuleHandle() from the DLL, so that you get the HMODULE of the executable that is running. It serves the same purpose as LoadLibrary() without having to go through the DllMain() and other initializations that LoadLibrary() will do.

    Regards,

    Paul McKenzie

  6. #6
    Join Date
    Apr 1999
    Posts
    27,427

    Re: How to call a C function (in the host process) from a DLL

    Quote Originally Posted by alexe100 View Post
    I am sorry, but you did not understood my problem!
    I understand it quite well.

    You have two options:

    1) Either you pass the pointer to the HelloWorld function to the DLL as a callback and from the DLL just issue the callback.
    or
    2) You use GetModuleHandle() using the process handle, use GetProcAddress() to get the HelloWorld function pointer (assuming it's exported), and then call the function.

    In neither of these scenarios do you need to link to the HelloWorld function.
    HelloWorld function does not belongs to dll! It belongs to the process!
    How does that change things? There is nothing stopping you from doing this:
    Code:
    LoadLibrary("myexe.exe"); // or
    GetModuleHandle("myexe.exe");
    an EXE and a DLL are modules that can have exported functions and can be loaded using LoadLibrary()/GetModuleHandle(). So why were you not attempting to do this before? From the Func() DLL, just call GetModuleHandle("yourexename.exe") and retrieve the HelloWorld function pointer, then call it.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 25th, 2013 at 05:00 PM.

  7. #7
    Join Date
    Jul 2013
    Posts
    4

    Re: How to call a C function (in the host process) from a DLL

    I never thought that I could call LoadLibrary for an EXE!

    Now all makes sense for me!

    Thanks a lot

    Alex




    Quote Originally Posted by Paul McKenzie View Post
    I understand it quite well.

    You have two options:

    1) Either you pass the pointer to the HelloWorld function to the DLL as a callback and from the DLL just issue the callback.
    or
    2) You use GetModuleHandle() using the process handle, use GetProcAddress() to get the HelloWorld function pointer (assuming it's exported), and then call the function.

    In neither of these scenarios do you need to link to the HelloWorld function.
    How does that change things? There is nothing stopping you from doing this:
    Code:
    LoadLibrary("myexe.exe"); // or
    GetModuleHandle("myexe.exe");
    an EXE and a DLL are modules that can have exported functions and can be loaded using LoadLibrary()/GetModuleHandle(). So why were you not attempting to do this before? From the Func() DLL, just call GetModuleHandle("yourexename.exe") and retrieve the HelloWorld function pointer, then call it.

    Regards,

    Paul McKenzie

  8. #8
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    5,976

    Re: How to call a C function (in the host process) from a DLL

    Quote Originally Posted by alexe100 View Post
    On dll, .cpp file, on top: __declspec(dllimport) void HelloWorld(void);
    Quote Originally Posted by alexe100 View Post
    It is a link error!
    Exactly. As long as you declare HelloWorld as imported, you're obliged to provide an import library for the function. As the module that exports it is your EXE, so the implib must be test1.lib. And you built it prior to building your dll. This scenario makes sense only in case your dll is strictly intended to be used with module named test1.exe and exporting HelloWorld function. And you won't be able to load it to any other process. I would recommend to think twice before implicit linking dll to exe function.
    Best regards,
    Igor

  9. #9
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,013

    Re: How to call a C function (in the host process) from a DLL

    Quote Originally Posted by Paul McKenzie View Post
    You have two options:

    1) Either you pass the pointer to the HelloWorld function to the DLL as a callback and from the DLL just issue the callback.
    or
    2) You use GetModuleHandle() using the process handle, use GetProcAddress() to get the HelloWorld function pointer (assuming it's exported), and then call the function.
    Just to add, a third option could be to place the function to be called from the DLL in a second DLL that both the application and (the first) DLL can link against. That way you can be sure the function exists at compile time, rather than at run time.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  10. #10
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    5,976

    Re: How to call a C function (in the host process) from a DLL

    Attached you can find a few sample projects that demonstrate:
    • pure C callback (callback-pure-c)
    • pure C++ callback - calling callback interface (callback-pure-cplusplus)
    • EXE export - explicit link to callback (exeexport-dynlink)
    • EXE export - implicit link to callback (exeexport-implib)


    As for me, pure C/C++ callback is the simplest way to organize the call. No need to mess with export from EXE (and possibly have a headache with name mangling, build order dependencies, etc.)
    Attached Files Attached Files
    Best regards,
    Igor

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center