Link/C-calling convention ?
-
Hello, I have a tricky situation happening in an app which loads a DLL and then tries to retrieve some procedure's addresses. Consider the following code:
void CDesktopPositionerDlg::OnCapture()
{
DFUNC_DEF(CDesktopPositionerDlg::OnCapture);
BOOL (__stdcall *lpSetup)();
BOOL bRetVal;
//!CODE_START--->
bRetVal = theApp.m_hModule != NULL;
if(!bRetVal)
goto loc_ret;
// inform user
lpSetup = ::GetProcAddress(theApp.m_hModule, "Setup");
bRetVal = lpSetup != NULL;
if(!bRetVal)
{
DTRACE(DSTR("Could not retrieve dll function address (err.#%d)", ::GetLastError()));
goto loc_ret;
}
// call function now
(*lpSetup)();
.
:
.
// return location
loc_ret:
DFUNC_RET2(bRetVal != FALSE, "Mouse hook not setup!", "Mouse hook successfully setup");
}Now notice the call to
::GetProcAddress
. If you change the name of the setup function to_Setup@0
, which is the name defined in the.LIB
file, all is fine and the hook is successfully setup. What I would like to know is the linker option (or C calling convention) I have to adopt in order to prevent such situations from happening. As always, all comments are welcome. David -
Hello, I have a tricky situation happening in an app which loads a DLL and then tries to retrieve some procedure's addresses. Consider the following code:
void CDesktopPositionerDlg::OnCapture()
{
DFUNC_DEF(CDesktopPositionerDlg::OnCapture);
BOOL (__stdcall *lpSetup)();
BOOL bRetVal;
//!CODE_START--->
bRetVal = theApp.m_hModule != NULL;
if(!bRetVal)
goto loc_ret;
// inform user
lpSetup = ::GetProcAddress(theApp.m_hModule, "Setup");
bRetVal = lpSetup != NULL;
if(!bRetVal)
{
DTRACE(DSTR("Could not retrieve dll function address (err.#%d)", ::GetLastError()));
goto loc_ret;
}
// call function now
(*lpSetup)();
.
:
.
// return location
loc_ret:
DFUNC_RET2(bRetVal != FALSE, "Mouse hook not setup!", "Mouse hook successfully setup");
}Now notice the call to
::GetProcAddress
. If you change the name of the setup function to_Setup@0
, which is the name defined in the.LIB
file, all is fine and the hook is successfully setup. What I would like to know is the linker option (or C calling convention) I have to adopt in order to prevent such situations from happening. As always, all comments are welcome. DavidI must ask, however inconvinient it sounds, what is the situation you wish to prevent ? Are you, per chance, failing to retrieve the address of the function, unless you name the parameter of
GetProcAddress
to "_Setup@0" ? How did you export the function from the DLL ? Or was it built by someone else ? Was it built with Visual Studio ? These questions are imperative, mostly because if the last answer is positive, there are two ways of exporting functions from a DLL. If you have access to the DLL code, you should add a__declspec(dllexport)
calling convention in front of the setup function. Also, create a module definition file (.DEF) inside the DLL project. Paste the following text into itLIBRARY "MyDLL.DLL"
EXPORTS
Setup @0When you now build the DLL, the GetProcAddress will not fail if you use "Setup" as the function name. Before, you built the DLL using the default settings. In such a case, the exported routines are added with the underscore in front of them. It is called 'behaviour by default' in Microsoft's terms. The only way to remedy it is to use a module definition file. The
__declspec
definition is added for increased compatibility, as in, fail-safe exporting. Also, if you're using dynamic loading (LoadLibrary), the library file is useless. Library files generated for DLL's are only usable if static linking is used, or if the DLL contains a registered COM component (DirectX applications, for an example). -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible. -
I must ask, however inconvinient it sounds, what is the situation you wish to prevent ? Are you, per chance, failing to retrieve the address of the function, unless you name the parameter of
GetProcAddress
to "_Setup@0" ? How did you export the function from the DLL ? Or was it built by someone else ? Was it built with Visual Studio ? These questions are imperative, mostly because if the last answer is positive, there are two ways of exporting functions from a DLL. If you have access to the DLL code, you should add a__declspec(dllexport)
calling convention in front of the setup function. Also, create a module definition file (.DEF) inside the DLL project. Paste the following text into itLIBRARY "MyDLL.DLL"
EXPORTS
Setup @0When you now build the DLL, the GetProcAddress will not fail if you use "Setup" as the function name. Before, you built the DLL using the default settings. In such a case, the exported routines are added with the underscore in front of them. It is called 'behaviour by default' in Microsoft's terms. The only way to remedy it is to use a module definition file. The
__declspec
definition is added for increased compatibility, as in, fail-safe exporting. Also, if you're using dynamic loading (LoadLibrary), the library file is useless. Library files generated for DLL's are only usable if static linking is used, or if the DLL contains a registered COM component (DirectX applications, for an example). -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.Hi Antti and thanks for the reply. :) Antti Keskinen wrote: Are you, per chance, failing to retrieve the address of the function, unless you name the parameter of GetProcAddress to "_Setup@0" ? That's it basically. After having finished the DLL I tried to access some of its functions in my MFC App by calling
GetProcAddress
and passing the names of the functions. It didn't work. Well it happens that, after taking a look at the .MAP file, all the functions are added the underscores and also some additional characters. Therefore, trying to retrieveSetup
's proc address from the Dll would only work if I called GetProcAddress passing_Setup@0
. I don't really know the workarounds one has/can do in order to prevent this from happening. I mean, how can I export the function as is, making it accessible by its true name? Will I have to create a definition file for the Dll? Again, thanks for the reply. By the way, I am using the__declspec(dllexport)
calling convention. -
Hi Antti and thanks for the reply. :) Antti Keskinen wrote: Are you, per chance, failing to retrieve the address of the function, unless you name the parameter of GetProcAddress to "_Setup@0" ? That's it basically. After having finished the DLL I tried to access some of its functions in my MFC App by calling
GetProcAddress
and passing the names of the functions. It didn't work. Well it happens that, after taking a look at the .MAP file, all the functions are added the underscores and also some additional characters. Therefore, trying to retrieveSetup
's proc address from the Dll would only work if I called GetProcAddress passing_Setup@0
. I don't really know the workarounds one has/can do in order to prevent this from happening. I mean, how can I export the function as is, making it accessible by its true name? Will I have to create a definition file for the Dll? Again, thanks for the reply. By the way, I am using the__declspec(dllexport)
calling convention.If you want to be sure by what name a function is exported, use a module definition file and rebuild the DLL. For example:
// In DLL code, somewhere
__declspec(dllexport) int Setup(void);// The module definition file
LIBRARY "MyDLL.DLL"EXPORTS
Setup @1This would export the Setup function from the DLL with it's true name, and
GetProcAddress
will not fail if you ask it to look for a function called "Setup". Also, using both the __declspec and the definition file is just about making sure it works. It will not get exported twice. Also, you can rename the exported symbols in the module definition file. Assuming that Setup is still the function name inside the DLL you wish to export, the following statement under EXPORTS would rename this symbol:Exported1 = Setup @1
Now, requesting "Exported1" with GetProcAddress would return the address of "Setup". However, asking for "Setup" would return an error. Basically, the difference on which one to use depends on if you want a library file (.LIB) or not. The __declspec(dllexport) adds an entry to the library file, so that if you link with this library file, you can call the exported functions, and the DLL will be loaded and the function executed (static linking). However, if you use dynamic (run-time) loading, the module definition file is the only way to specify the names of the exported functions explicitly. It is not possible to use a library file with dynamic loading. This will not work, it is just not designed to work that way. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.
-
If you want to be sure by what name a function is exported, use a module definition file and rebuild the DLL. For example:
// In DLL code, somewhere
__declspec(dllexport) int Setup(void);// The module definition file
LIBRARY "MyDLL.DLL"EXPORTS
Setup @1This would export the Setup function from the DLL with it's true name, and
GetProcAddress
will not fail if you ask it to look for a function called "Setup". Also, using both the __declspec and the definition file is just about making sure it works. It will not get exported twice. Also, you can rename the exported symbols in the module definition file. Assuming that Setup is still the function name inside the DLL you wish to export, the following statement under EXPORTS would rename this symbol:Exported1 = Setup @1
Now, requesting "Exported1" with GetProcAddress would return the address of "Setup". However, asking for "Setup" would return an error. Basically, the difference on which one to use depends on if you want a library file (.LIB) or not. The __declspec(dllexport) adds an entry to the library file, so that if you link with this library file, you can call the exported functions, and the DLL will be loaded and the function executed (static linking). However, if you use dynamic (run-time) loading, the module definition file is the only way to specify the names of the exported functions explicitly. It is not possible to use a library file with dynamic loading. This will not work, it is just not designed to work that way. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.
Great stuff Antti! That is exactly what I was looking for! Thanks a lot for the invaluable feedback, Antti. - David