I'm trying to link against a dll that I have all the source for, but I can't get access to a dirt simple class I've created in it without getting LNK2019's.
I made this:
class makeprob
{
public:
makeprob();
~makeprob();
};
with the implementation:
makeprob::makeprob() { }
makeprob::~makeprob() { }
as a nice simple template. Then in my actual project, I have the following:
#include "evil_dll.h"
class PC
{
public:
PC() { };
~PC() { };
static makeprob ProblemCreator;
};
with the implementation:
#include "evil_dll.h"
makeprob PC::ProblemCreator;
When I then try to link against it and construct a makeprob class, I get
LNK2019 unresolved external symbol "public: __thiscall makeprob::makeprob(void)" (??0makeprob##QAE#XZ) referenced in function "void __cdecl `dynamic initializer for 'public: static class makeprob PC::ProblemCreator''(void)" (??__E?ProblemCreator#PC##2Vmakeprob##A##YAXXZ)
I've checked that I'm linking against the lib and I am. From everything I can tell, the dll is a 32 bit dll to go with my 32 bit app. I am already using functions from the dll, but they've been declared with __declspec(dllimport)
I have to admit; I'm all thumbs with this. I have no idea if I'm supposed to do anything specific on the receiver to bring a class across from a dll. This is part of a school test, and part of the instructions tell me I don't need to edit the source code (just use the provided classes). I only created the makeprob class to make the problem simple to post up here.
Any advice would be invaluable! Thank you so much!
Scheff actually answers this in the comments above, just formalizing it for Stack Overflow, but Scheff deserves all the cool-haircut-and-rayban-sunglasses points.
My problem is the class implementation doesn't export the constructor or destructor. My makeprob header file above should read like this:
class makeprob
{
public:
__declspec(dllexport) makeprob();
__declspec(dllexport) ~makeprob();
};
to have access to those. Scheff further suggests using macros for this (which I have found they already exist: systemAPI) instead of writing it out manually.
This doesn't get around my professor telling me I don't need to edit the source, but since all the other functions of the class I'm importing have systemAPI in front of them, and only the constructor and destructor don't, I'm gonna call it an oversight? Unless there is a fancy way to import a class without its constructor/destructor.
Thanks everyone!
Related
Is there any difference between class __declspec(dllexport) class_name and __declspec(dllexport) class class_name?
I know it seems odd. But a strange thing happened to my code.
First I open my c++ Dll project in Visual Studio 2017 and add a class as usual. Compiling process is fine. But when I use another console to use my Dll, the linking process told me that unresolved external symbol referenced. What confused me most is that my new class's constructor and destructor functions are those missing symobls. Here I use the implicitly-declared default constructor and destructor.
I tried to explicit the constructor and destructor, It doesn't work and it still told me that I missed these two function.
I tried to check the calling convention. The dll and console are all set to __cdecl and I believe that's not the reason.
I suppose there is something wrong with my "#include". I tried, but nothing good happend.
I accidently exchange the order of the name of the class and right result came out.
Now, I'm really confused about __declspec(dllexport). If there is no difference between these two, how to explain this?
Note that I define the PATHPLANNINGLIB_EXPORTS macro in the preprocessor definitions.
#ifdef PATHPLANNINGLIB_EXPORTS
#define PATHPLANNINGLIB_API __declspec(dllexport)
#else
#define PATHPLANNINGLIB_API __declspec(dllimport)
#endif
namespace CCSP_PlanningAlgorithm
{
using PathMap = std::map<SERobot*, std::vector<WayPoint>>;
//PATHPLANNINGLIB_API class MOutput //sucess declartion
class PATHPLANNINGLIB_API MOutput //failed declartion, why??
{
public:
long path_result_ID;
PathMap path_map;
};
}//CCSP_PlanningAlgorithm
I expected everything goes fine. I just use this class to save my final data result. But the linking process failed and I can't run my program.
The test console program gave me this error message:
LNK2019 无法解析的外部符号 "__declspec(dllimport) public: __cdecl CCSP_PlanningAlgorithm::MOutput::MOutput(void)" (__imp_??0MOutput#CCSP_PlanningAlgorithm##QEAA#XZ),该符号在函数 "public: static void __cdecl MyTestCase::myStaticTest(void)" (?myStaticTest#MyTestCase##SAXXZ)
I have two modules, each with own class and with own object. Each module is compiled to a DLL. I want to make a "cross-DLL" method call, having pointer to the object of another class, but linker doesn't allow to do this (MSVC++ 2008).
More specifically:
there is calledModule.cpp, that has calledClass, and object of this class (calledObject); class has calledMethod, which I want to call; module is compiled to DLL and becomes (surprise!) calledLib.dll.
there is callingModule.cpp, that has callingClass; among other things, the class has the attribute, which is a pointer to the calledObject; module is compiled to DLL callingLib.dll; the pointer on calledObject is set in the constructor.
I'm able to compile the whole code. The trouble comes when the linker starts. I'm getting the following:
moduleCalling.obj : error LNK2001: unresolved external symbol "public: void __thiscall classCalled::methodCalled ..."
I don't use any declspec things, so nothing is exported from the calledLib.dll.
The method that I'm calling (methodCalled) is present in the implementation, its prototype is correctly declared in header. The classCalled is a "basic" class, not inherited from anything.
Moreover, the whole project compiles and working correctly, when I declare methodCalled as a virtual...
I have troubles understanding, why I can't call the method of the object in a "normal" way from another DLL? Why declaring it as a "virtual" helps? Anyone knows? I have some guesses, but expert answer will help a lot to understand this stuff.
P.S.: I'm using MSVC++ 2008.
Thanks!
Update: adding code snippet, which reflects, how the code looks like.
// part of calledLib.dll
// moduleCalled.h
class classCalled {
public:
int methodCalled() { return 1 };
};
// ---------------------------------------------------------------
// part of callingLib.dll
// moduleCalling.h
#include "moduleCalled.h"
class classCalling {
public:
classCalled* ref;
void justSomeMethod();
};
// ---------------------
// moduleCalling.cpp
#include "moduleCalling.h"
void classCalling::justSomeMethod() {
ref = new classCalled();
int a = ref->methodCalled(); // <--- this is not allowed by linker,
// unless methodCalled is made virtual.
}
Linker links pieces of code from various modules. If you have a call from one module to another, linker has to know in which other module the function you're invoking is implemented and substitute the call by the real address. This is a very rough picture, but it's enough to understand what is going on.
In your case the linker has to know that your function is located in calledLib.dll. Therefore you have to link with something that refers to calledLib.dll. This something is called an import library. It's name should be calledLib.lib. In order to generate it you either should write a .def file, but it's difficult for class methods, since class methods names used by linker look very different from what they look like in your C++ code. Or you can use declspecs. It will generate the proper calledLib.lib, which you will have to link with your callingLib.dll.
I am working on a simple top down shooter and wanted to move my ships to a separate ShipManager class, where I can manage all of them from a single location. However, upon starting this I get a linker error on my playerShip:
error LNK2001: unresolved external symbol "public: static class Ship * ShipManager::playerShip"
ShipManager.h looks like this:
class Ship;
class ShipManager
{
public:
static Ship* playerShip;
};
I have nothing in the ShipManager .cpp yet. What am I missing? The only other place I use this code is in my game class where I am actually calling ShipManager::playerShip, and I don't get any errors there.
I include "ShipManager.h" in my game.cpp, so it should find it right? I have a feeling I'm forgetting something simple in this class.
Static members have to be defined somewhere. You are declaring playerShip, but not defining it. You need to add somewhere, necessarily and only one cpp file:
Ship* ShipManager::playerShip;
You only declared the static member, you also need to define it in (only)one of your cpp files:
Ship* ShipManager::playerShip;
Good Read:
What is the difference between a definition and a declaration?
I'm trying to compile some other people's wrapper program on a large system, in which it's using a global object from another file, the definition of the class is like:
class __declspec(dllexport) A
{
...
static A * instance;
}
And in my separate source file (which I want to build to a .exe), I included the header file A.h, and declare at the beginning like this
A * A::instance;
to access the data in A.
The problem is, this piece of code can be built successfully on Linux, now when I try to build it in windows NT, it will have issues.
If I leave it like this, the compiler will complain with a C2491 error, definition of dllimport function not allowed.
If I remove this line of A declaration, I'll get a lot of error LNK2001: unresolved external symbol.
Not quite sure what is the problem here, I did some research online, but couldn't find a good answer, I myself is not that familiar with dll import/export and some C++ tricks either. Can some one provide some insights on the problem or which direction should I spend my time on to figure this out?
Or say, if I already have a static object like this, and I want to write another program to access it, how exactly should I do?
Please also correct me if I made any mistakes here. Thanks!
I think the keyword you need is extern, as in:
extern A *A::instance;
This says the variable A::instance is defined somewhere else, but you're telling the compiler about it so you can use it by name in this file.
__declspec(dllexport) is used when you want to export your function in a DLL. It should not be necessary as long as you're not calling the class from another DLL.
But I suspect your problem is related to using .c files and not the class specification. Try to read this by the way. It discusses dllexport in just-enough-detail Windows & C++: extern & __declspec(dllimport)
Singleton usually has a function, like
A::instance = NULL;
A * get_instance() {if (!A::instance) A::instance = new A; return A::instance;}
If you have a function like this you don't have to access A::instance directly.
And sorry, but what are you doing? Including a C++ header in a C program? Does it even compiles?
Personally I usually hide the instance in the .cpp file in an anonymous namespace. Then I provide a getInstance() function that returns a pointer or reference to it and I dllExport that function.
If you want to enforce things you can make the constructors for A private and make getInstance a friend.
So I'm trying to build a small 3D engine as an exercise on VC++ 8.0. I have a MathLib static lib and a Render static lib that is being linked by my TestBed exe. Right now Render has two classes: Color and DXManager3D. Color includes my Vector.h from MathLib just fine, no problems.
The second I try to include Vector.h in DXManager3D it blows up on me, saying the symbol is defined twice, and the second definition is ignored (warning from lib). I thought maybe including it twice was causing this so as a test I removed Vector.h from Color.h and left it in DXManager3D.h - same problem. I have triple checked to make sure I have everything wrapped in ifndef to protect from this, so I am left scratching my head.
DXManager3D.obj : warning LNK4006: "public: __thiscall Math::Vector::Vector(void)" (??0Vector#Math##QAE#XZ) already defined in Render.obj; second definition ignored
What really confuses me is that when I build the Render.lib separate from TestBed, which should not be linking anything as it is a static lib, right? I still get the multiple symbol definition warnings. If I instantiate a DXManager3D in main my warnings become errors.
Render.lib(DXManager3D.obj) : error LNK2005: "public: __thiscall Math::Vector::Vector(void)" (??0Vector#Math##QAE#XZ) already defined in WinMain.obj
Yes, I have F1'd LNK4006 and LNK2005 and the solutions in the MSDN aren't working for me.
Sorry if this question has been asked before, I couldn't find anything solid to help me out using the search feature.
Thanks!
Is your Vector ctor defined in the header outside the class definition? Make it inline then i.e. change
class Vector {
public:
Vector();
// ...
};
Vector::Vector() {
// ...
}
to
class Vector {
public:
Vector() {}
// ...
};
or use an explicit inline qualification:
class Vector {
public:
Vector();
// ...
};
inline Vector::Vector() {
// ...
}
It looks like you have a linkage issue with your vector class. Based on your information it appears that the class is being linked into any lib which includes the header file. This is internal linkage, and you really want external linkage.
Can you post the contents of Vector.h, or at least the Vector() constructor? That should give us a clue to what is actually going on.
Linkage: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr020.htm
EDIT
Based on your comment, it appears that you have declared all of the functions in the header file outside the class library. You should put them into a non-header file (Vector.cpp file for instance).
This will give your program the appropriate linkage and you will be able to include Vector.h in both programs.