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).
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'm creating a DLL project with Visual Studio 2012 with the intent of calling the functions from a Delphi project. I've already turned off C++ name mangling by wrapping my functions in extern "C" { /* ... */ } but to avoid the C name decoration, I'm using a DEF file.
Here's a snippet of code describing how I have things laid out:
// MyFile.h
#ifdef MYPROJECT_EXPORTS
#define MYPROJECT_API __declspec(dllexport)
#else
#define MYPROJECT_API __declspec(dllimport)
#endif
extern "C" {
extern MYPROJECT_API void __stdcall do_something();
}
The .cpp file is equivalently structured. Everything matches fine.
I added a .def file to my project folder containing the following content:
LIBRARY MyProject
EXPORTS
do_something=_do_something#0
When I build my project, everything works okay. However when I add the linker option
/DEFS:MyProject.def
I start getting errors regarding unresolved external symbols. Has anybody had this kind of issue before? I'm not new to either C++ or C but this is my first time building a DLL on Windows, as I'm primarily a Unix developer. My hypothesis is that I'm either misunderstanding or misusing the __declspec decorator, as it only breaks when I link in the def file: when I remove that flag from the linker options it builds cleanly, except with C-style decorated symbols.
EDIT: Thanks for the comments everyone, but I've gotten myself figured out now. My issue came from the fact that I was using the def file during the linking phase during creation of my DLL. I need to use the def file when using the DLL, not creating it, and everything is peachy.
Thanks for the comments everyone, but I've gotten myself figured out now. My issue came from the fact that I was using the def file during the linking phase during creation of my DLL. I need to use the def file when using the DLL, not creating it, and everything is peachy.
I create two projects in VC++ Express 2010, one is DLLTest, the other is CODETest.
In DLLTest, declare and define a function func() as follows:
__declspec(dllexport) void func() {...};
Build DLLTest project successfully, DLLTest.dll and DLLTest.lib files created.
In CODETest, i want to use the exported function as follows:
#include "DLLTest.h"
int main()
{
...
func();
...
return 0;
}
Error occurs when build CODETest project--->"unresolved external symbol "void __cdecl letterList(void)" , but when i add DLLTest.lib into directory of CODETest project, build process successfully.
I dont know why? Thanks for help.
This seems all pretty unlikely, especially the part where "func" transformed into "letterList". Nevertheless, you have to tell the linker to also link the import library of the DLL so that it can resolve identifiers that are imported from that DLL. The easiest way to do that in MSVC is:
#include "DLLTest.h"
#pragma comment(lib, "dlltest.lib")
in CodeTest.cpp. The #pragma does the same thing as the linker's Additional Dependencies setting.
(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.