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
Related
I need to create a dll which contains stuff I have in my executable project in visual studio 2010. I realized instead of creating a dll project, I can just change the project configuration in project properties >> General >> 'configuration type' to 'dll' and it builds fine. It creates the dll. I added an additional .h/.cpp files which contains the export functions I want in the dll.
My first concern is that is this a legit dll? I am trying to load it using LoadLibrary() but I get error code 126 (The specified module could not be found) although the dll is in the project directory (same as executable). I am just wondering if it has to do with the fact it may not be a fully qualified dll for any reason? My exe project is MFC project.
** Update **
Thanks to the comments, I can now load the dll successfully - it was dependencies issue. However GetProcAddress() doesn't return valid pointer for the export function. The dumpbin /exports utility shows the dll has no export functions!
So I have added just .h/cpp files to the original project which has a simple dummy function for export right now.
__declspec(dllexport) int MakeDouble(int value);
I also included the header file in the app class just in case. I am wondering why does this function does't appear as an export? What do I have to do?
First:
__declspec(dllexport) int MakeDouble(int value);
Function declaration should have the same signature than the definition and, of course, the function must have a definition (at simple return 0; should work }
Second:
The exported function name is decorated with beautiful weird characters, you should use extern "C" (or the MS specific stdcall + the .def file).:
//.h
extern "C" __declspec(dllexport) int MakeDouble(int value);
//.cpp
extern "C" __declspec(dllexport) int MakeDouble(int value) {
return 0;
}
You should also check in project properties the option:
Configuration Properties -> C/C++ -> Code Generation -> Runtime Library
Make sure the value contains the word DLL.
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.
After googling, i came to know that Dllimport makes the function available for other modules,
is it mandatory to declare function with extern "c" identifier?
Also, Dllexport means, Dll itself uses the function while compiling it says. so by default all
functions present in DLL are dllexport?
__declspec(dllexport) exports a symbol. It makes it available from outside a DLL.
__declspec(dllimport) imports a symbol. It practically says "this symbol is not defined in this application, it needs to be imported from a DLL file".
You don't have to declare it with extern "C". If you don't use extern "C", then the symbol will be exported as a C++ symbol, and you will only be able to call it from C++ (and languages that support calling C++ DLLs). If you use extern "C", then the symbol will be exported as a C symbol, and you will be able to call it from languages that support caling C DLLs.
If you want to use your DLL in C#, you will need to use extern "C".
Here is an excellent tutorial that shows you how to use a C++ DLL in C#: How to marshal a C++ class. I have used solution A in many projects at work.
Also, here is a short tutorial on how you can use a C++ DLL in another C++ application: How to create and use DLL in C++.
No -- dllexport means you're exporting it from the DLL (or from an executable) so that other modules (DLLs or executables) can use that function.
dllimport is used to declare a function that's implemented in a DLL (or, again, executable).
So, in a typical case, you'll have something like:
#ifdef BUILDDLL
#define DLL declspec(dllexport)
#else
#define DLL declspec(dllimport)
#endif
Then each public function the DLL will be marked as DLL:
DLL int dosomething(int);
Then, when you're building the DLL, you'll define BUILDDLL, to have all those functions marked as dllexport. Otherwise, you'll include the same header in client code that needs to use the function(s). It won't define BUILDDLL, so they'll all be marked as dllimport instead, so when it comes to link time, it'll create a link to that DLL instead of trying to satisfy those functions from someplace like the standard library.
It also means that entries (in the form of static import and export tables) are created (by the linker) in the exe, dll..files, which document the dependencies between a provider and a consumer.
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).
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