I have got MyDll.dll and its function defined as below
void pascal Myfunction(BOOL);
when I'm trying to use the function in another project i am unable get the address of the function with GetProcAddress(). Here is my code:
void callMyDll()
{
HINSTANCE hDll;
hDll=LoadLibrary(_T("MyDll.dll");
if(hDll!=NULL)
{
cout<<"\n DLL Loaded \n";
}
else
cout<<"\n DLL Not loaded\n"
typedef void (__stdcall *MyFunction)(bool)
Myfunction mf1 = (MyFunction) GetProcAddress(hDll, "MyFunction");
if (mf1!=NULL)
cout<<"\n Function Loaded Successfully \n";
else
cout<<"\n Function not loaded \n";
FreeLibrary(hDll);
}
I'm getting output as:
DLL Loaded
Function not loaded
But when I'm trying with known DLLs like glut32.dll and its functions it is working fine.
I think it may be problem with its function like
void pascal MyFunction(BOOL);
Can anybody help me in this regard?
You need to use extern "C" to prevent name mangling and ensure the function is exported:
extern "C" __declspec(dllexport) void Myfunction(BOOL);
To view the exports from your DLL you can use dumpbin.exe utility that is shipped with Visual Studio:
dumpbin.exe /EXPORTS MyDll.dll
This will list the names of all exported symbols.
In addition to this do not have either of the following compiler switches specified:
Gz __stdcall calling convention: "Myfunction" would be exported as Myfunction#4
Gr __fastcall caling convention: "Myfunction" would be exported as #Myfunction#4
Note: I think last symbol is dependent on compiler version but is still not just "Myfunction".
The DLL export process is subject to name mangling and decoration. The long obsolete 16 bit pascal calling convention is equivalent to stdcall on 32 bit platforms.
First of all you should use extern "C" to specify C linkage and disable name mangling.
However, your function will still be subject to name decoration. If you export it with __declspec(dllexport) then it will in fact be exported with the name _Myfunction#4. If you wish to export it by its true name then you need to use a .def file.
However, the possibility still remains that you did not export the function from the DLL at all. Use Dependency Walker to check whether it was exported, and if so by what name.
Why are you using the pascal calling-convention? Perhaps that alters the names of symbols, and if so you might need to take that into account.
The symbol is going to be decorated, so it will never be called MyFunction, its more likely _MyFunction#4. you can quickly check this using something like dumpbin.
You can read up more on mangling here, if you want to avoid mangling, you need to use a def file to specify symbol names (or ordinals).
Related
I have created example of using static libraries. The goal is this functionality:
DllTestFunctDll.dll links static_lib.lib (contains fnStaticLibrary())
example.exe links DllTestFunctDll.dll (contains dllTestFunct())
main() calls directly fnStaticLibrary() and dllTestFunct().
dllTestFunct() calls directly fnStaticLibrary().
I don't understand one thing, this works only if fnStaticLibrary() is inside same project as main() and dllTestFunct().
If I create another solution that
DllTestFunctDll.dll links also static_lib.lib (contains fnStaticLibTest())
main() newly also calls directly fnStaticLibTest().
dllTestFunct() newly also calls directly fnStaticLibTest().
dllTestFunct() is able to call fnStaticLibTest() and main() is unable to call fnStaticLibTest() due to linker. But I am able to call fnStaticLibTest() inside dllTestFunct().
I used dumpbin to see what functions are exported:
dumpbin /EXPORTS "C:\\path\\DllTestFunctDll.dll"
Output:
ordinal hint RVA name
1 0 00001000 ?dllTestFunct##YAXXZ = ?dllTestFunct##YAXXZ (void __cdecl DllTestFunct(void))
2 1 00001070 ?fnStaticLibrary##YAXXZ = ?fnStaticLibrary##YAXXZ (void __cdecl fnStaticLibrary(void))
You can see that fnStaticLibTest() is missing inside the output.
In both static lib projects I export function by "__declspec(dllexport) ".
I assume that the problem is inside the Visual Studio. Do you know how to solve it?
Thank you in advance for your answers.
CODE (VS17 solution) LINK: https://github.com/Ales5475/StaticLibProblemExample
An object module is added from a .lib, if it is required. If the dll does not call (or reference) any item in a compilation unit (c/cpp file), it won't be added to the dll
This behavior is important for libraries, as it ensures that when linking against the C/C++ runtimes, then you don't import the whole of the libraries. Just those which are required.
In your case you have a DLL which doesn't require the test function, and a .EXE which expects the DLL to have it. There is no visible requirement for the test function when the DLL is being built.
A DLL has explicit exports. Either
__declspec(dllexport)
or a .DEF file with exports. In this case, it appears that the static lib doesn't know if it is in a DLL or the EXE, so isn't decorated with declspec(dllexport) the best solution is for the .def file for the DLL to explicitly export the function.
The code in StaticLibTest.h
__declspec(dllexport) void fnStaticLibTest();
is inconsistent with the code in StaticLibTest.cpp
void fnStaticLibTest(){
This will not cause the function to be exported. In general include a file which declares a function / structure to ensure it is consistent.
The correct form is
void __declspec(dllexport) fnStaticLibTest(){
and
void __declspec(dllexport) fnStaticLibTest();
Otherwise you are adding the attribute to the void.
Here is the snippet I did use #pragma comment successfully.
DLL:
__declspec(dllexport) void DllTestFunct();
...
#pragma comment(linker, "/export:fnStaticLibTest")
void DllTestFunct() {
fnStaticLibrary();
fnStaticLibTest();
printf("Hello world (Dynamic library)!\n");
}
DLL's dependency:
Header Folder:
XXX\StaticLibTest\StaticLibTest;
XXX\MainProgram\StaticLibrary;
DLL Folder:
XXX\StaticLibTest\x64\Debug;
XXX\MainProgram\x64\Debug;
DLL input:
StaticLibTest.lib;
StaticLibrary.lib
Static Lib:
extern "C" void fnStaticLibTest();
...
extern "C" void fnStaticLibTest() {
printf("Hello World! (Static library from another project)\n");
}
I've read several articles here on name mangling/decoration and keep running into inconsistencies so I thought I would ask a pretty focused question and see what happens.
I am trying to work my way up the learning curve to eventually be able to create a dll in VS2013 that is usable by code generated on a very old Borland C++ compiler. The first step is to build an exe and dll in VS2013 that can "talk". I want undecorated function names. So I have created a dll with one exported function.
extern "C" __declspec(dllexport) int __cdecl BasicFileOpen(void);
My limited understanding is:
extern "C" means no decoration
__declspec(dllexport) means export the function
__cdecl specifies the calling signature (how parameter get put on the stack, etc)
When I examine the dll using DependencyWalker or Dumpbin /EXPORTS, the function name is undecorated. Yay.
Here is the code in the exe that attempts to call the exported function in the dll:
void CCallsCIDdllDlg::OnBnClickedOk()
{
int iRetVal = BasicFileOpen();
// TODO: Add your control notification handler code here
CDialogEx::OnOK();
}
However, when I try to build the exe, I get a linker error.
error LNK2019: unresolved external symbol _BasicFileOpen referenced in function
"public: void __thiscall CCallsCIDdllDlg::OnBnClickedOk(void)"
(?OnBnClickedOk#CCallsCIDdllDlg##QAEXXZ)
Note that the exe mentions _BasicFileOpen.
I am puzzled by this.
I have correctly pointed at the lib file produced by the dll build.
I am including the header file for the dll function in the exe.
Why doesn't the linker understand the name of the exported function?
Why does it think the function name is decorated?
BTW using a .def file does not seem to make any difference.
Any comments are appreciated.
MBB
I have worked with "CPPLoadLibrary" example (from Microsoft All-in-One framework)
Okay, there are two ways of export symbols from the sample DLL.
Export symbols from a DLL using .DEF files
A module-definition (.DEF) file is a text file containing one or more module
statements that describe various attributes of a DLL. Create a .DEF file and
use the .def file when building the DLL. Using this approach, we can export
functions from the DLL by ordinal rather than by name.
Export symbols from a DLL using __declspec(dllexport)
__declspec(dllexport) adds the export directive to the object file so we do
not need to use a .def file. This convenience is most apparent when trying to
export decorated C++ function names.
And so we have the following code.
typedef int (_cdecl* LPFNGETSTRINGLENGTH1) (PCWSTR);
typedef int (CALLBACK* LPFNGETSTRINGLENGTH2) (PCWSTR);
LPFNGETSTRINGLENGTH1 lpfnGetStringLength1 = (LPFNGETSTRINGLENGTH1)
GetProcAddress(hModule, "GetStringLength1");
LPFNGETSTRINGLENGTH2 lpfnGetStringLength2 = (LPFNGETSTRINGLENGTH2)
GetProcAddress(hModule, "_GetStringLength2#4");
So my question is how to determine the name of symbol in order to call GetProcAddress?
in first case it's pretty straightforward, we take that symbol name from .DEF file.
But what about "_GetStringLength2#4"
What is underscore? What is "#4" stand for?
Thanks.
If you don't use a .DEF file, the export names are decorated according to their calling convention in order to support exporting overloaded functions. See Why can't I GetProcAddress a function I dllexport'ed?:
[T]he decoration scheme varies from architecture to architecture and from calling convention to calling convention. So, for example, if the function is exported from a PPC DLL, you would have to do GetProcAddress(hinst, "..SomeFunction"), but if it is exported from an 80386 DLL as extern "C" __stdcall, you would need GetProcAddress(hinst, "_SomeFunction#8"), but if it's __fastcall you would need GetProcAddress(hinst, "#SomeFunction#8").
What's more, C++ decoration varies from compiler vendor to compiler vendor. A C++ exported function might require GetProcAddress(hinst, "?SomeFunction##YGXHH#Z") if compiled with the Microsoft C++ compiler, but some other decorated string if compiled with the Borland C++ compiler.
So if you intend people to be able to GetProcAddress for functions and you intend your code to be portable to multiple platforms, or if you intend them to be able to use your DLL from a language other than C/C++ or use a C++ compiler different from Microsoft Visual Studio, then you must export the function by its undecorated name.
See The history of calling conventions, part3 for a description of the various name decoration schemes. In this case, the function uses the __stdcall calling convention, so it's decorated by prepending an underscore and appending a # sign and the number of bytes worth of parameters it takes. It takes one word-sized argument for a total of 4 bytes, so it's decorated as _GetStringLength2#4.
To answer your actual question, use your compiler's TDUMP or similar tool, or any other tool that can display an executable's exports table, so you can see the actual exported names.
I'm working on a DLL which will be used from another language (so no import libs and including the dll's headers) using the _stdcall calling convetion. The problem is that VC++ seems to always do some name decoration on its exported symbols. All the references ive seen say use extern "C" but this still seems to leave me with a leading underscore, and a # plus a number after the exported name.
The worst bit is the automated means of loading extension dll's in the target language essentially does "func_name = GetProcAddress(dll, "func_name")" so using an undecorated name GetProcAddress fails, and using the decorated name it complains of an illegal variable name (# is not allowed) :(
How can I make VC++ export somthing with no name decorations at all?
extern "C" __declspec(dllexport) int __stdcall test(int x, const char *str);
dumpbin.exe
00011366 _test#8 = #ILT+865(_test#8)
You can use a .def file. It will let you export the functions without the decorations.
Read: Exporting from a DLL Using DEF Files
I am importing an C++ DLL in an Inno Setup install script. The DLL code is as follows:
void __stdcall SetFbParam(
char *dbFileName,char *dbTableName,char *dbParamName,char *dbParamValue) {
// of no use here and doesn't change anything
}
In the Inno Setup, I import it using
procedure FBset(dbFileName,dbTableName,dbParamName,dbParamValue: String;);
external 'SetFbParam#files:MyDll.dll stdcall setuponly';
However, I always get a runtime error during launch of the installer, saying that it cannot import my dll. I tried it with various calling conventions, but it always fails.
If it's of any importance, I'm running Win7 x64 with UAC on (the installer requests rights elevation and crashes after that).
The exact message is:
Error
Runtime error (at -1:0):
Cannot import
dll:C:\Users\Nevod\AppData\Local\Temp\is-6LOEC.tmp\MyDll.dll
The dll is there.
Thanks!
Is MyDll.dll 32-bit?
Does MyDll.dll depend on any other DLLs in the same directory? If so, you need to list the name(s) of those DLLs after MyDll.dll to ensure that they are extracted before MyDll.dll is loaded, and you likely need the loadwithalteredsearchpath option as well. Example from the help:
procedure ADllFunc(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal);
// A.dll depends on B.dll
external 'ADllFunc#files:A.dll,B.dll stdcall loadwithalteredsearchpath';
(I know it is old but maybe some other hits this one too)
Most probably the name of the function is mangled in the C++ DLL. I had the same problem and I was able to solve it by recompiling the dll. In short:
If you export from C++ something like:
void __stdcall foo()
you will get a function called (Visual Studio):
?foo##YGXXZ
To prevent name mangling you should use extern "C" directive. Example (Visual Studio)
extern "C" __declspec( dllexport ) void __stdcall foo()
However I have found that Visual Studio will continue to mangle and you get something like:
_foo#0
The sole way I was able to get clean names is explained here:
C++ DLL Export: Decorated/Mangled names
And the culprit is indeed __stdcall. If you remove that from your declaration:
extern "C" __declspec( dllexport ) void foo()
you will again get a clean export, even without a DEF file. IMO this should be good enough, as the code above declares a "C" exported function and the default calling convention for C is stdcall. However I haven't had the time and disposition to validate this as adding a DEF file is way easier than navigating asm code and check stack pointers :)
In order to use DLLs in Inno Setup's [Code] section please make sure:
DLL is in 32 bit mode (even if the installer is built for 64bit and is running in 64bit mode)
exported functions have
extern "C" __declspec( dllexport )
modifier
use cdecl calling convention because stdcall mangles name (https://learn.microsoft.com/en-us/cpp/cpp/stdcall). Of course it is possible to specify mangled name in Inno Setup import statement. But it seems easier to just use cdecl.
As mentioned in other answers, do not forget to embed all dependencies of your DLL. Though if it is your DLL, better might be to get rid of (or at least reduce) the dependencies.
For example when building C++ DLL in Visual Studio, link the runtime statically, not dynamically.
In project Properties, go to C/C++ > Code Generation > Runtime Library and select Multi-threaded (not DLL).
There are also tools that can embed other external dependencies.
See Embedding DLLs in a compiled executable