My experience is with Delphi XE2 and I am not familiar with MS Visual C/C++. I am trying to compile some MS Visual C++ code into a DLL I can use from Delphi.
The compiled DLL exported functions cannot be found by Delphi.
Using a hex editor the DLL export table looks like the following snippets and does not have NULL terminated function names (a NULL ASCII char is positioned following the eol "Z"):
?MM_End##YAH_N#Z
?MM_GetCurrentPosition##YAHPAN0000#Z
?MM_GetWindow##YAHPAN000#Z
?MM_MarkGetLinkFile##YAHPAXPADH#Z
?MM_Start##YAH_N#Z
The C++ header code looks like this:
...
#define MMAPI_API __declspec(dllexport)
...
MMAPI_API int MM_Start(bool run_mmnav);
MMAPI_API int MM_End(bool close_mmnav);
...
With reference to https://msdn.microsoft.com/en-AU/library/dt232c9t%28v=vs.90%29.aspx. I have tried several variations of __stdcall and _cdecl but cannot get MS Visual C++ to compile the export table with NULL terminated strings.
You are attempting to reverse engineer, by guesswork, a format that is well documented. The PE format is known and documented. There's no point in you trying to reverse it with a hex editor. There's no need for you to understand the format at all. Use an existing tool to list the exported functions. For instance dumpbin from the MS tool chain, or Dependency Viewer.
Once you've listed the exports you'll find that they have been exported under their C++ mangled names. Name mangling is how C++ compilers encode the function signature in the function name used for linking. Mangling was designed to allow C++ tool chains to support overloaded functions and continue using C style linker technology.
You'll see a list of exported symbols like these:
?MM_Start##YAH_N#Z
?MM_End##YAH_N#Z
etc.
Run these through a demangler to confirm that they are what you are expecting. The above symbols demangle as:
int __cdecl MM_Start(BOOL)
int __cdecl MM_End(BOOL)
You can import them using those names if you wish. For example:
function MM_Start(run_mmnav: BOOL): Integer; cdecl;
external dllname name '?MM_Start##YAH_N#Z';
function MM_End(run_mmnav: BOOL): Integer; cdecl;
external dllname name '?MM_End##YAH_N#Z';
Or you can choose to suppress C++ name mangling of the exported functions when you compile the DLL. Do that by wrapping the function declarations in an extern "C" block, or by exporting the functions with a .def file.
Related
I have a library of DSP functions in C++ and I want to link to them dynamically at run time. I am using the PDLL.h method to wrap my classes (for example FFT) into C-style functions and load them load on the fly in other C++ applications. I want to use these functions in .NET applications and COM components, so I have to use __stdcall which decorates the names in 32 bit builds.
In order to undecorate the names, I am using the trick mentioned here: C++ DLL Export: Decorated/Mangled names (wqw's answer, 2nd down). So for example, in my library's .h file I have declared my wrapped functions so:
#pragma comment(linker, "/EXPORT:DoFFT=_DoFFT#12")
RTLIBS_API DoFFT(FFT* x, DOUBLE* pdDataIn, DOUBLE* pdDataOut);
This does indeed work, and when I look into the dll with dependency walker, I see that there is both an entry for DoFFT and _DoFFT#12.
The problem that I have is that when I try to build a project that links to this library (dynamically, at run time, not using the .lib file at all) I get linker errors for all the functions in my dll, i.e.:
Error 31 error LNK2001: unresolved external symbol _DoFFT#12
I don't understand why this is happening. First of all, the symbol _DoFFT#12 does exist (according to dependency walker) and second of all, why is the linker looking for it in the first place? I am linking to it at run time, not at compile time so how does my project even know about this symbol?
All the functions are declared with the same chain of macros that reduces to (e.g.):
extern "C" __declspec(dllexport) int __stdcall DoFFT(FFT* x){...}
Nothing having to do with the library is declared on the client side.
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 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'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've got to support an old app written in C using the old Borland Compiler (BC 5).
Unfortunately the old TCP/IP library that we'd used is starting to show it's age and is having problems with Vista & Win7 machines.
I have a new library of functions available for MS Visual C++, and I'd like to use that to make a DLL that would be callable from the Borland C.
So, I have 2 issues:
1) how to make a Visual C++ DLL callable from a Borland C program, and
2) if it is callable, how to call the C++ functions from plain old C?
Ideally, the entire project should be converted to Visual C, but there a lot of legacy features that'll make that project a major undertaking! I'm looking for a quick patch to keep it alive for a while longer :)
Steve
Write a DLL using Visual C++ that exposes its interface as Windows STDCALL C functions. Windows API functions are done similarly. Those functions you expose in the interface will perform the functions you need to replace in your program. Inside the DLL, call the new MS VC++ library with abandon.
So to get a function that is callable from C and uses STDCALL stack protocol do something like this:
extern "C" int __stdcall foo();
you'll also have to add information to export the function from the DLL. You might do this explicitly in the declaration as such:
extern "C" __declspec(dllexport) int __stdcall foo();
But you'll need a separate header file for use in your BorlandC code (which probably has different syntax for specifying the DLL import part and the STDCALL part). In Visual C++ the declaration you'd use in the client would look something like:
extern "C" __declspec(dllimport) int __stdcall foo();
You can create Borland OMF import libaries with Borland's IMPLIB utility: IMPLIB -a "whatever.omf" "whatever.dll", where the DLL file is that created by MSVC.
The -a option is for Microsoft compatibility. The generated OMF (Borland's import library file format), combined with a header file that specifies the exported functions and their calling convention(s) should work... (I believe IMPLIB was around in C++ Builder 5.)
http://docs.embarcadero.com/products/rad_studio/radstudio2007/RS2007_helpupdates/HUpdate4/EN/html/devwin32/implib_xml.html