This has been discussed in parts on many places, but it still wont work for me.
I have a dll compiled from delphi source, which exports one function under two names, inspecting the dll using
>> dumpbin /EXPORTS MyLibrary.dll
i get the following output:
...
17 3 00070A88 MyFunction
...
46 24 00070A88 _MyFunction@48
...
so i created a file called MyLibrary.def with the following content:
EXPORTS
MyFunction
_MyFunction@48
And generated an import library using
>> lib /def:MyLibrary.def /OUT:MyLibrary.lib /MACHINE:x86
Inspecting the new lib-file with dumpbin i see the following:
...
_MyFunction
...
__MyFunction@48
...
So somehow the lib application added one underscore in front of the function name. (why?)
Then i try to use this function in a c++ program, compiling with Microsoft Visual Studio C++ 2010 Express (using the lib file):
// MyLibrary.h
# define DllImport(Type) __declspec (dllimport) Type __stdcall
extern "C" DllImport(void)MyFunction(...);
// main.cpp
#import "MyLibrary.h"
...
MyFunction(....);
...
This should now work, as far as i could find out, but i get the following linker error:
... error LNK2001: Unresolved external sympol "__imp__MyFunction@48".
I don't understand why this goes wrong (i dont realy understand how the whole thing works ...) but i tried two more things.
- Renamed my function in MyLibrary.h and main.h from MyFunction to _MyFunction
- Result: it works! But why? I dont want to rely on this, since something is obviously wrong.
- Renamed my function back to MyFunction and removed the underscore in the def-File, generated the lib file again and tried to compile
- Result: compilation succeeds, but when starting the program i get
MyApp - Entry Point Not Found
---------------------------
The procedure entry point MyFunction@48 could not be located
in the dynamic link library MyLibrary.dll.
I think one needs a deeper understanding of the inner working of the lib tool and the linker, but i couldn't find any information about this so far.
KB131313 explains one problem you'll face trying to use the lib
utility for this:
The only time you can use a .DEF file to create an import library from a .DLL for which you do not have the source code or object modules is if the .DLL exports functions via a C interface. Specifically, the functions need to have been declared to use the C calling convention.
Your functions uses stdcall, not cdecl, as we can tell from the @
in the function name. Nevertheless, the KB article explains what to do instead:
Declare the function as it would be in C++, but for export instead of for import.
You've already done that, mostly. You have the calling convention right, but the @48
on the end means it needs to have 48 bytes' worth of parameters. The function will expect to have that data pushed on to the stack, and before it returns, the function will pop that much off. Your use of ...
in the declaration is incompatible with that.
If you don't know what the specific argument list should really be, then go ahead and just define 12 int
parameters, so at least the stack structure will be right. (But if you don't know what the list should really be, you're pretty close to doomed anyway.)
Write a dummy implementation in C++.
The implementation can be empty. The only requirement is that the code compiles and links.
Compile your own version of MyLibrary.dll from that dummy code.
Make sure it's compatible with the original DLL. Run dumpbin
on it and see that it exports at least one version of the function names you saw in the original DLL. (You don't need both; your program is only going to use one of the names, and as the dumpbin
output shows, both names go to the same location in the binary, so it doesn't matter which name your program ends up using.)
Throw away the DLL and keep just the LIB file.
- Use the lib file to link with the real DLL.
If the linker still complains that it cannot find __imp_MyFunction@48
, then remove the dllimport
part from your declaration. That should remove the __imp_
prefix, making the name look more like the Delphi name.
If all else fails, you can use run-time dynamic linking instead of load-time. Declare a pointer type for the function, and then use LoadLibrary
and GetProcAddress
to get access to it.