I am trying to build a dll to go along with my program in c++. The dll will be a basic library with a bunch of inheritable classes and general utilities, which can then be used dynamically by multiple other applications that will accompany the final product(A Game). I threw something together, only to find that I am recieving I maddening error. It is the famous "error LNK2019: unresolved external symbol". First off, I already found the solution to this, and here is the link: Unresolved External Symbol- Error in guide?
The chosen answer works. If I put my class into only a header file, it compiles perfectly fine, runs, and is all nice and pretty. However, I want to keep the declaration and implementation separate, and if I try to move the implementation to a separate cpp I receive the LNK2019 error. This is due to some kind of inlining, I just want to know how I can bloody fix it before I start tearing my hair out.
Can anyone help me with this? Here is my class:
Header:
#ifndef MYDLLTESTCLASS_H
#define MYDLLTESTCLASS_H
class __declspec( dllexport ) MyDLLTestClass {
public:
MyDLLTestClass();
void setX( int x );
int getX();
private:
int x;
};
#endif // MYDLLTESTCLASS_H
CPP:
#include "MyDLLTestClass.h"
MyDLLTestClass::MyDLLTestClass() {
}
void MyDLLTestClass::setX( int x ) {
this->x = x;
}
int MyDLLTestClass::getX() {
return x;
}
Separate like above, the code wont compile. But if I throw the declaration and implementation together It works, so if I do this:
#ifndef MYDLLTESTCLASS_H
#define MYDLLTESTCLASS_H
class __declspec( dllexport ) MyDLLTestClass {
public:
MyDLLTestClass();
void setX( int x );
int getX();
private:
int x;
};
MyDLLTestClass::MyDLLTestClass() {
}
void MyDLLTestClass::setX( int x ) {
this->x = x;
}
int MyDLLTestClass::getX() {
return x;
}
#endif // MYDLLTESTCLASS_H
It will work. Again, I WANT the declaration and implementation separate.
Here is the build report when I use separate declaration and implementation.
http://pastebin.com/HMEpeEgn
This was actually far easier to solve than I realized; it turns out the it was a visual studio setting all along. First, you need to add the dll project to your current project(Which will be using it). Then you need to right click on you current project and Follow these two pictures:
And then add your dll, which might just need to be check-marked(Mine was simply missing the checkmark).
After that your project will compile perfectly fine! No need for nasty-ass #ifndef macros like every webpage has attempted to portray(which also didn't work mind you)
Related
I am new to C++ but not to programming. I'm developing a plugin and learning the language at the same time. The plugin is for old software but still being used, so I'm using VS2015 and an SDK to match. I'm having a problem that I just don't know enough to solve but I know that it's the result of something that I'm doing wrong or don't understand. Please also consider that I'm using a third party SDK, with only .H/.HPP files and an occasional .CPP, but that's it. Everything else is wrapped in their libraries. Therefore, I don't have the liberty to change any behavior.
My code snippets are parts of their headers (can't change) and the .cpp is my modified sample code that comes along with their SDK and which I'm using as my base. It is also the area of code that causes the link error. Their samples all work, I can compile them and run them no problem. My code also works and is doing what I want. Things only break when I use my modified code. The reason I'm doing this is because I need access to the message passed into the plugin and can't find any other way to get it other than to try and override "PluginMain". The original sample code actually does call into PluginSetup.cpp because it runs other code within it as setup prior to continuing on. I've only posted the part of my code which is my attempt to override the function as I mentioned and I just included the variable declaration that causes the error. If I comment my variable declaration and other code related to it, program compiles and works again. If I move the variable declaration to another .cpp file in my codebase, code compiles no problem. It just don't like being in PluginSetup.cpp but part from maybe the main.cpp file (which I can't do anything with), PluginSetup.cpp is the first that gets called. So this is where I chose to put my override.
Am I using the friend function correctly? As you can see from the codebase, they've made the ctor as well as the friend function private.
This may also go hand in hand with a question I asked before on how to instantiate a class from this implementation using private friend function and ctors?
Hopefully, what I've posted is enough to give someone all that's needed to figure out what the problem might be.
ns1ns2Main.h
namespace ns1
{
namespace ns2
{
class Plugin;
...
}
}
extern "C" __declspec(dllexport) __MainError PluginMain(const char* caller_, const char* selector_, void* message_);
ns1ns2Plugin.h
#include "ns1ns2Main.h"
namespace ns1
{
namespace ns2
{
class Plugin
{
Public:
static Plugin* const instance();
private:
friend __MainError (::PluginMain) (const char*, const char*, void*);
Plugin();
Plugin(const Plugin&);
virtual ~Plugin();
};
}
}
PluginSetup.cpp
#include "ns1ns2Main.h"
#include "ns1ns2Plugin.h"
//-> My Modification Begins
__MainError (::PluginMain) (const char* caller, const char* selector, void* message)
{
ns1::ns2::Plugin plugin;
if (!plugin.instance())
{
plugin = ns1::ns2::Plugin();
}
if (strcmp(caller, kSPInterfaceCaller) == 0)
{
if (strcmp(selector, kSPInterfaceStartupSelector) == 0)
{
bool bStatus = ns1::ns2::pluginSetup(&plugin);
if (bStatus)
{
plugin_ = clpcsx::Plugin::instance();
plugin_->startup();
}
}
else if (strcmp(selector, kSPInterfaceShutdownSelector) == 0)
{
plugin_ = clpcsx::Plugin::instance();
plugin_->shutdown();
}
}
return error;
}
//<- My Modification Ends
namespace ns1
{
namespace ns2
{
void pluginLoaded()
{
// no-op
}
bool pluginSetup(Plugin* const plugin)
{
clpcsx::Plugin::create(plugin);
plugin->setStartupCallback(NS1_NS2_CALLBACK(clpcsx::Plugin, CLPCSX_PLUG_INST, startup));
plugin->setPostStartupCallback(NS1_NS2_CALLBACK(clpcsx::Plugin, CLPCSX_PLUG_INST, postStartup));
plugin->setPreShutdownCallback(NS1_NS2_CALLBACK(clpcsx::Plugin, CLPCSX_PLUG_INST, preShutdown));
plugin->setShutdownCallback(NS1_NS2_CALLBACK(clpcsx::Plugin, CLPCSX_PLUG_INST, shutdown));
return true;
}
void pluginDestroy(Plugin* const plugin)
{
clpcsx::Plugin::destroy();
}
}
}
Link Error
1>PluginSetup.obj : error LNK2019: unresolved external symbol "private: __cdecl ns1::ns2::Plugin::Plugin(void)" (??0Plugin#ns2#ns1##AEAA#XZ) referenced in function PluginMain
You have to tell the linker to include the libraries. Since this is VS you can add to the main .cpp file
#pragma comment(lib, "xxxx.lib")
where 'xxxx.lib' is the name of the library that has those ns functions. You need to make sure they are in the VS linker path too
I am new to C++, so I am sorry if this a simple or obvious error. I have been reading a lot other questions and the documentation, but I haven't been able to find a solution yet.
I am trying to add a new class definition to a large existing project. Everything compiles perfectly fine without my additions. However, when I add my code below I get a LNK2019 error on the constructor method (and any additional method). I have noticed adding/referencing properties does not cause this linker error, only the methods. Below is the most simple example that produces the error:
Header:
namespace foo
{
class bar_interface
{
public:
//My code
#ifndef Point_H
#define Point_H
class Point
{
public:
Point(int x, int y);
};
#endif
//existing code
void onStartup();
}
}
Class:
//My code
#ifndef Point_H
#define Point_H
class foo:bar_interface::Point{
public:
Point(int x, int y)
{
};
};
#endif
//existing code
void bar_interface::onStartup()
{
foo::bar_interface::Point p( (int)8, (int)8 );
//continue existing code
}
Error 1 error LNK2019: unresolved external symbol "public: __thiscall
foo::bar_interface::Point::Point(int,int)"
(??0Point#bar_interface#foo##QAE#HH#Z)
referenced in function "public: void __thiscall
foo::bar_interface::onStartup(void)"
(?onStartup#bar_interface#foo##QAEXXZ)
I realize that probably do not need such explicit calls to Point or casting the numbers as ints, but I wanted to make sure I wasn't missing anything obvious (removing them doesnt change the error). I have tried moving the 'Point' class to its own file and defining it outside the 'bar_interface' but within the 'foo' namespace. Removing the #ifndef code creates a C2011 redefinition error. I am at a loss for how to proceed.
Unresolved external means that the definition is missing, that is that the linker cannot find an implementation of the named function.
Somewhere you need:
namespace foo
{
bar_interface::Point::Point(int,int)
{ ... }
}
Remove all your lines from the code above that start from # and the reason of the issue becomes cleaner.
For the life of me I cannot figure out what is causing this... I keep getting unresolved external symbol error. However, if I put an empty definition in the header file it compiles correctly.
WINMAIN.CPP
#include "FILE_XXX.H"
int WINMAIN WinMain(...)
{
EnableOpenTest(); // call like this
return 0;
}
FILE_WORKS_CORRECTLY.H
#ifndef _FILE_WORKS_CORRECTLY_
#define _FILE_WORKS_CORRECTLY_
void EnableOpenTest() { }
#endif
However, when I do something like this (correctly), it does not work and I get a compile-time error.
FILE_DOES_NOT_WORK_CORRECTLY.H
#ifndef _FILE_DOES_NOT_WORK_CORRECTLY_
#define _FILE_DOES_NOT_WORK_CORRECTLY_
void EnableOpenTest();
#endif
FILE_DOES_NOT_WORK_CORRECTLY.CPP
#include "FILE_DOES_NOT_WORK_CORRECTLY.H"
void EnableOpenTest() { /* do work here */ }
UPDATE:
Upon further investigation, I found the issue has to do with me having multiple projects in the same solution. I then try to reference a function in one project from another project. Obviously I'm doing this incorrectly.
The only mistake i see is that in the cpp file you need to include the return type as well. It should be
void EnableOpenTest()
{
//Enter Code Here
}
Inside of FILE_DOES_NOT_WORK_CORRECTLY.CPP:
EnableOpenTest(){ /* do work here */ }
must be
void EnableOpenTest(){ /* do work here */ }
Looks like your compiler sets the missing return type to int instead of yelling at you with a error message.
You should turn on compiler warnings, it would allow you to notice such errors very quickly.
Also, inside of FILE_WORKS_CORRECTLY.H you have another error:
void EnableOpenTest() { }
must be
inline void EnableOpenTest() { }
Otherwise it will trigger a error message if this header is included twice (i.e. in more that one .cpp file).
Solved it!
Additional projects needed to be static library (main project .exe)
Added References of library projects to main project
Obviously the file structure caused a lot of these issues.
I face a very strange link problem with VC 2010. Now I am developing a C++ library, and in order to make debug much easier, for some functions the library provides two function interfaces. For example,
class Object
{
public:
int fun(std::vector<int> &auxiliary_variable_for_debug_purpose);
int fun();
}
It is also possible to reorganize this class in this way:
class Object
{
public:
#ifdef DEBUG_INDICATOR
int fun(std::vector<int> &auxiliary_variable_for_debug_purpose);
#else
int fun();
#endif
}
By doing so I except to give a clear interface to the user.
The problem I face now is both int fun(std::vector<int> &auxiliary_variable_for_debug_purpose); and int fun(); will invoke another function called void help_function(), which is declared and defined in separated files.
file.h
void help_function()
and
file.cpp
void help_function()
{
// do something
}
As you can see void help_function() is the same regardless whether DEBUG_INDICATOR is defined or not. If I defined DEBUG_INDICATOR, I can compile the class with int fun() function without any problem. However, when I undefined DEBUG_INDICATOR, the error LNK2001 error happens, suggesting unresolved external symbol void help_function(). I have tried every possible means to figure it out, but failed. Any ideas will be appreciated.
EDIT
The library I have built is a dynamic library. Regardless whether DEBUG_INDICATOR is defined, the library can be built, and the link error only happens when the library is invoked.
Since you've not posted the exact error message you are getting, this MSDN link might help you.
Tip: Be specific while asking your question if you wish to receive accurate answers.
I've been trying to compile a multi-file project, but every time I try to use a void in player.cpp, I keep getting this error message, which appears that the player.o that is created during compilation has the same definition of void player_action(...). When I tried to use a void in the other files, the same problem occurs, with their corresponding .o file. However, if I use structs in any of the files, no problems occurs, and no "multiple definition" error occurs. In the lines below is the error message the compiler is giving me.
obj\Debug\player.o: In function `Z13player_actioniii':
D:/Projects/Blackmail Mailman/player.cpp:13: multiple definition of `player_action(int, int, int)'
obj\Debug\main.o:D:/Projects/Blackmail Mailman/player.cpp:13: first defined here
This is the code from player.cpp I used:
#include "include_files.cpp"
struct player_struct
{
int x;
int y;
int previous_x;
int previous_y;
int mode;
};
void player_action(int x, int y, int mode)
{
SDL_Event event;
if (SDL_PollEvent(&event))
{
if (event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDLK_RIGHT:;
};
};
};
};
What could be wrong and how can I fix it? I'm using Codeblocks with Mingw and Windows XP. I already checked the other files and there aren't any extra definitions of void player_action().
You never #include .cpp files, rather the .h files only.
If you need to access void player_action() from several parts of your program you should make a header file myapi.h which contains the following:
//myapi.h
#ifndef MYAPI_HEADER
#define MYAPI_HEADER
void player_action(int x, int y, int mode);
/* more function declarations */
#endif
The file which defines the function will be like this:
//player.cpp
#include "myapi.h"
void player_action(int x, int y, int mode)
{
/*...*/
}
and the file which uses it will be like this:
//main.cpp
#include "myapi.h"
void GameCycle()
{
/*...*/
player_action(0,0,0);
/*...*/
}
Never include objects definitions with #include, unless you know what you are doing. And even if you do know, you should think twice before doing so. Always use include guards (#ifndef ... #define .. #endif) - this will prevent multiple inclusion of your header.
These are the basic recommendations. I have seen a good explanation of such stuff in B. Stroustrup's 'The C++ programming language'