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'|
Re: How to call a C function (in the host process) from a DLL
Originally Posted by alexe100
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()?
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.
Re: How to call a C function (in the host process) from a DLL
Originally Posted by alexe100
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.
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
Originally Posted by Paul McKenzie
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.
Re: How to call a C function (in the host process) from a DLL
Originally Posted by alexe100
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.
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
Originally Posted by Paul McKenzie
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.
Re: How to call a C function (in the host process) from a DLL
Originally Posted by alexe100
On dll, .cpp file, on top: __declspec(dllimport) void HelloWorld(void);
Originally Posted by alexe100
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.
Re: How to call a C function (in the host process) from a DLL
Originally Posted by Paul McKenzie
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
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.)
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.