Exporting an undecorated function name - c++

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

Related

trouble linking to de-decorated DLL names in C++ (32 bit) in Visual Studio

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.

DLL needs symbols (a class) from the app it will link to

I cannot get a DLL to link, that needs a class exported from the app this DLL will be used with. Visual Studio 2008, Windows 7.
I had a small sample DLL compiling (the default MSFT DLL project actually), and the app can use LoadLibrary() and GetProcAddress() on it correctly. I'm experienced with dllimport/dllexport. Using dumpbin /exports was critical to discover the mangled names to use with GetProcAddress() (MSFT's default empty DLL includes a sample function without extern "C") but this is a solved problem.
The next step was to have the app export a class that the DLL will need to subclass. I do the dllimport/dllexport #define's in the reverse sense from usual: a special symbol when the app is compiled tags the class with dllexport and non-app code (such as the DLL) using that header, without the special symbol, gets a dllimport spec. dumpbin /exports on the .exe file shows exactly this class's (mangled) symbols being exported, and no others, as expected.
The next step was to have the DLL include the header and create an object of the exported object's type (as a baby-step towards actually subclassing it). Compiles fine, but linker shows error:
DynTest.obj : error LNK2019: unresolved external symbol "public: __thiscall Test::Test(class Toast*,double)" (??0Test##QAE#PAVToast##N#Z) referenced in function "public: __thiscall CDynTest::CDynTest(void)" (??0CDynTest##QAE#XZ)
OK, that didn't surprise me, as I know on WIN32 I need to supply DLL's at link time to make a DLL, unlike my usual Unix. Since Windows seems to treat DLLs and executables a bit similarly, I tried adding the .exe at Properties->Configuration Properties->Linker->Input->Additional Dependencies. That gets an error that looks like LINK.EXE didn't auto-detect that it was being given an .exe:
T:\mypath\MyBinary.exe : fatal error LNK1107: invalid or corrupt file: cannot read at 0x348
I then tried adding instead the object file that defines this class... That seems to be understood by the linker, and is probably successfully satisfying the DLL's need to link, but now shows a myriad of other symbols this file depends upon.
So I've considered refactoring the app such that most of it is in a DLL or LIB, just so I can supply that as an "Additional Dependencies" to the DLL I'm actually worried about. But this seems to be draconian. Is that my only option?
Invoking dumpbin /exports gives you a list of mangled names of exe exports. You need to create a module definition file (.def) containing these names:
EXPORTS
#d3d_some_fancy_mangedled_method_1
#d3d_some_fancy_mangedled_method_2
...
Notice that it is basically dumpbin output with first columns removed.
Then you use lib tool to generate export library from module definition file:
LIB /DEF:prog.def /NAME:prog.exe /MACHINE:x86
Finally you link generated export library prog.lib into your application. /MACHINE option should match to your executable. Notice that you don't need to link or anyhow use program executable to link it, only export library is used.

Unable to export functions from C++ DLL

I need to create a C++ MFC DLL using Visual Studio 2008. To do this I created a DLL MFC Win32 Console project in Visual Studio and made a function that creates an object and uses its method to print a string to the screen. Kind of like this:
__declspec(dllexport) void Foo(void);
where:
void Foo(void){
print* obj = new print;
obj->testPrint();
return;
}
void print::testPrint(void){
printf("Bar\n");
return;
}
It compiles successfully and generates the DLL, but when I try to use it I always get:
"error LNK2019: unresolved external symbol "void __cdecl Foo(void)"
I tried using Dependency Walker and it doesn't show any function up in the DLL. Am I doing something wrong? I've searched a lot and still got no conclusions from what may be happening.
Sounds like you may not have included the header file which specifies the export in any cpp file. Remember that the cpp files are the only ones actually compiled. So make sure you include the header with the __declspec(dllexport) void Foo(void); in at least one cpp file. Also make sure that your project Linker->Input settings don't have a 'Module Definition File' (def) file specified.
Don't bother trying to link to the DLL until dependency walker shows that something is actually exported.
Windows defaults to cdecl so you need to make explicit that it's exported declspec in the caller - or export it from the DLL as cdecl instead.
You need to export the symbol explicitly from CPP file also:
__declspec(dllexport)
void Foo(void)
{
print* obj = new print;
obj->testPrint();
return;
}
The specification in header is merely for the client (EXE), and a hint for the linker from the server (DLL).

Regarding GetProcAddress

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).

LNK2019 when converting an app to use DLLs

(Re-written for clarity)
I have a multi-project solution that I am looking to convert from using .lib to .DLL files. I have created my __declspec macros and applied it to every class except for those in the project that creates the final .exe. The linker is throwing a fit on just about everything, however. I have set up to ignore errors about exporting templated objects.
One example is this:
error LNK2019: unresolved external
symbol "__declspec(dllimport) public:
void __thiscall
Rail::SetNextRail(class Rail *)"
(__imp_?SetNextRail#Rail##QAEXPAV1##Z)
referenced in function "public: static
void __cdecl
MyUtilities::CreateBezierRails(int,class
MyVector *,class std::vector > &)" (?CreateBezierRails#MyUtilities##SAXHPAVMyVector##AAV?$vector#PAVRail##V?$allocator#PAVRail###std###std###Z) MyUtilities.obj
Unresolved external symbol on my __declspec(dllimport)? That doesn't seem right. It is getting placed by a macro such as:
#ifdef MYAI_EXPORT
#define DECLSPECAI __declspec(dllexport)
#else
#define DECLSPECAI __declspec(dllimport)
#endif
Basically, what gives? Why am I getting these errors and how can I fix them? Thank you to everybody who has tried to help thus far, but I am still stuck with this.
Are you linking against MyRenderer.lib?
Do you export your functions and classes using
__declspec(dllexport)
and import them using
__declspec(dllimport)
? If not, you will have to do this. In your header, during compiling the DLL, you will need to have the dllexport clause, and when using the header in other DLLs or EXEs, you will have to use the dllimport clause. You can easily do this by defining a macro like
// set this in preprocessor options for the DLL
#ifdef MYDLL
# define MYDLL_IMPORTEXPORT __declspec(dllexport)
#else
# define MYDLL_IMPORTEXPORT __declspec(dllimport)
#endif
class MYDLL_IMPORTEXPORT MyClass {};
Well its saying that it found a declaration but no implementation. Are you sure you are compilnig the file with the function implementation in it? Have you remembered to put the MyRenderer:: before the DrawVertices call? Are you sure you are linking both the libraries into the executable?
Edit: When compiling a lib the library leaves a stub, effectively, saying I want this function when you can link it to me.
When you run the linker it runs through all the libraries looking for these stubs and "links" them to the actual implementation. Each cpp file you build compiles to an object file and this object file works in exactly the same way. If it can't link the stub to the actual function then you get a linker error such as you are seeing. Thus, either your renderer library is not being linked into the executable OR the implementation is missing something vital such as the MyRenderer::. Though if it was the latter i'd expect other problems to arise such as the lack of a IDirect3DDevice which, i assume, is a member of the class. Thus, most probably, you are failing to link the .lib in.
there are different configurations of DLLs.
staticly linked DLL - the implementations are in a DLL, and the definitions are in a .lib. You statically link to the .lib (which is kinda like a header), and the lib tells c++ how to call the function. this is probably what you want. make sure you get your __declspecs right.
dynamically linked DLL - everything is in the DLL, the definitions are also in the DLL, you need to manually set up function pointers to all the exported things, which are indexed by a string at runtime.
Google will help and made this CW so someone can make this answer suck less.
i also advise you to get DLLs working in a skeleton app.