Linker errors for template macro: unresolved external symbol - c++

I am trying to build someone else's code in VS2010. It builds fine in VS2005, but I need to upgrade it.
They have defined a macro as follows in a header:
#include <boost/scoped_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/thread/once.hpp>
#define DEFINE_SINGLETON(name) boost::scoped_ptr<name> Singleton<name>::_instance
template<class T> class Singleton : private boost::noncopyable
{
public:
static T& instance()
{
boost::call_once(init, flag);
return *_instance;
}
static void init()
{
_instance.reset(new T());
}
protected:
Singleton() {}
~Singleton() {}
private:
static boost::scoped_ptr<T> _instance;
static boost::once_flag flag;
};
template<class T> boost::once_flag Singleton<T>::flag = BOOST_ONCE_INIT;
I've managed to get the code to build now, but I am getting lots of linker errors about this macro:
project1.lib(file1.obj) : error LNK2001: unresolved external symbol "private: static class boost::scoped_ptr<class ClassABC> Singleton<class ClassABC>::_instance" (?_instance#?$Singleton#VClassABC####0V?$scoped_ptr#VClassABC###boost##A)
An example of the macro being used (in source file):
#include "singleton.h"
DEFINE_SINGLETON(ClassABC);
I am quite new to Boost and also to templates (sorry), so I cannot fathom why I'm getting these errors when it all linked fine in VS2005. Its worth noting, that in order to do the upgrade we have also had to upgrade our Boost version, so this could be a factor - a few checks already performed:
Header file is included in source file
Boost dir is added to include dirs (under VC++ dirs inproperty pages)
Added boost lib dir to Linker -> General -> Additional library dependencies
For info, I am compiling a Multi-threaded debug dll on Win32.
I have spent most of the day googling to no avail, so any help greatly appreciated!
Many thanks :)

I don't see you used the macro anywhere in the posted code.
You need to use it as:
//add this line after BOOST_ONCE_INIT or before it, or wherever you see fit.
template<class T> DEFINE_SINGLETON(T);
Personally I would prefer this:
template<class T> boost::scoped_ptr<T> Singleton<T>::_instance;

Related

Static variable link error in MSVC even though it is created in the cpp file

I am working on a cross-platform (Linux & Windows) library. One of my class has a static member defined in the header. And I created it in a CPP file like
namespace raisim {
std::function<void()> RaiSimMsg::fatalCallback_ = []() { exit(1); };
}
The header file
#ifndef RAISIM_MESSAGE_LOGGER_HPP
#define RAISIM_MESSAGE_LOGGER_HPP
#include <chrono>
...
namespace raisim {
class RaiSimMsg {
public:
...
void stream(const char *file, const int line, std::stringstream &msg, int severity) {
if (severity == RSEVERITY_FATAL)
fatalCallback_();
}
private:
static std::function<void()> fatalCallback_;
};
}
#endif //RAISIM_MESSAGE_LOGGER_HPP
This works perfectly with GCC and Clang in Linux. But MSVC is giving a link error. Does MSVC have its own rules for static members??
Full error log
1>anymal.obj : error LNK2001: unresolved external symbol "private: static class std::function<void __cdecl(void)> raisim::RaiSimMsg::fatalCallback_" (?fatalCallback_#RaiSimMsg#raisim##0V?$function#$$A6AXXZ#std##A)
1>C:\Users\ultrafrog\source\repos\raisim\build\benchmark\Debug\speed_test_anymal.exe : fatal error LNK1120: 1 unresolved externals
1>Done building project "speed_test_anymal.vcxproj" -- FAILED.
Jack Dingler's answer here
https://www.codeproject.com/Questions/585271/Aplusstaticplusmemberplusvariableplusexportpluserr
worked. So the issue is that the Windows linker needs to know that if it has to import or export the symbol. So we have to declare __declspec(dllexport) when we export (when we build the library) and __declspec(dllimport) for using it. We can switch that using a compilation flag. I am not sure why they designed the linker like this but anyway it works now.

Is it possible to put implementation of a template member function which calls a static function in its header?

First of all, I have found some seemingly related threads in this forum, but they do not help. For example, 33182246 is about static template member function, but the template member function in my question is not static, and the error therein is not the one I encountered. 12229396 is another irrelevant thread in which answerers are quarreling about whether it is allowed to export a static. But I don't intend to export a static in dll, and the question I am going to ask has nothing to do with it. As for 1053097 which is the first in my search result here, it is not about C++ at all. So I think my question is a new one and here comes the problem.
Environment:
Windows 10 version 1803
Visual Studio 2015 Update 3
Debug x64 mode in VS
Source:
There are two projects in the solution:
1) DllProject, built as a dll, contains three sources: Dll.h, Dll2.h and Dll2.cpp.
Dll.h:
#pragma once
#include "Dll2.h"
#ifdef _WINDLL
#define API_TYPE __declspec(dllexport)
#else
#define API_TYPE __declspec(dllimport)
#endif
class API_TYPE AClass {
public:
template <class T> void CallFunc() {
BClass<T>::testStatic();
}
};
template void AClass::CallFunc<float>(); //explicit instantiation
Dll2.h:
#pragma once
template <typename T>
class BClass {
public:
static T m_Static;
static T testStatic();
};
template <typename T>
T BClass<T>::testStatic() {
return m_Static;
}
Dll2.cpp:
#include "Dll2.h"
template <typename T>
T BClass<T>::m_Static; //define the static
template class BClass<float>; //explicit instantiation
2) ExeProject, built as an exe, contains Exe.cpp.
Exe.cpp:
#include "Dll.h"
int main() {
AClass a;
a.CallFunc<float>();
}
The idea behind the solution structure is as follows. The exe program ExeProject calls functions in dll, with Dll.h specifying the interface. To abstract complexities as many large opensources do, Dll.h only provides a wrapper of the underlying details, and it is this wrapper that is called by exe. The details are implemented by a template class BClass in Dll2.h and Dll2.cpp. By design, BClass is used only inside the dll so it is not qualified with __declspec(dllexport). Since BClass is a template class, I explicitly instantiate it in Dll2.cpp at line 6. Because CallFunc is also a template, I explicitly instantiated it at line 27 of Dll.h. The problem is caused by the static member in BClass. Since it is static, I need to define it and this is done in line 3-4 in Dll2.cpp, so there is an m_Static static variable inside dll that the dll uses through static function testStatic(). The DllProject compiles correctly. The exe project ExeProject also compiles without any problem. But errors arise at linking time:
1>------ Build started: Project: ExeProject, Configuration: Debug x64 ------
1>Exe.obj : error LNK2001: unresolved external symbol "public: static float BClass<float>::m_Static" (?m_Static#?$BClass#M##2MA)
1>C:\tmp\TestStatic\x64\Debug\ExeProject.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========
As I said above, I have defined the static, I don't want the static to be exported, I have instantiated the template class BClass and the template member function CallFunc, I have specified API_TYPE to AClass so stuffs inside it should all be exported, but why still error?
The following are what I have tried. To make sure CallFunc is really exported from dll, I qualified it with API_TYPE
class API_TYPE AClass {
public:
template <class T> void API_TYPE CallFunc() {
BClass<T>::testStatic();
}
};
Then I received a compiling error: error C2491: 'AClass::CallFunc': definition of dllimport function not allowed. The same is true if I move the implementation out of the class.
However, everything works fine if I move the implementation of template function CallFunc out of the header Dll.h and into Dll.cpp:
Dll.cpp:
#include "Dll.h"
#include "Dll2.h"
template <class T> void AClass::CallFunc() {
BClass<T>::testStatic();
}
and accordingly Dll.h is changed to:
#pragma once
#ifdef _WINDLL
#define API_TYPE __declspec(dllexport)
#else
#define API_TYPE __declspec(dllimport)
#endif
class API_TYPE AClass {
public:
template <class T> void CallFunc();
};
template void API_TYPE AClass::CallFunc<float>(); //explicit instantiation
where #include "Dll2.h" is removed, only declaration of CallFunc is in AClass' declaration and API_TYPE is added to the explicit instantiation of CallFunc at the end (API_TYPE is really erratic to use. Sometimes it works without it but sometimes not).
Now this is my question. For some reason, I would like to keep the implementation of the template member function calling static function in the header Dll.h (out of the class preferably), but as you can see, VS insists on putting the implementation in a .cpp file. So, is there any chance to work around this restriction and have the implementation code stay in header in VS? Thank you.
The workaround I found is move the definition of static variable from Dll2.cpp to Dll2.h. The implementation is still residing in Dll.h, nothing big is changed and everything is now working. For those who have doubt, Visual Studio handles this very well: the static has only one instance in the memory, as expected, and they are not exported, as desired. Pound.
Since I have solved my question, I had planned to just delete it, but I am surprised to see the downvote. Following is what I would like to say to this downvoter: I think I know what you are thinking: Sigh! This question is so low. The answer is all in the documentation or C++ Standard which I can recite immediately without even a single glance at it. I am an expert of C++, I can't tolerate such a low question ...
OK, I agree you are, but this question is all about problem-solving, without any intention to deeply discuss the theory of programming language so that I can write a phd dissertation. A practical problem does not have to be solved by showing off a profound mastery of the topic concerned. Just a small surface modification would suffice like what I did described at the beginning. So stop your arrogance and be open to all possibilities so that you can learn some problem-solving skills. It is not only good to you, but also good to the SO as a whole.

LNK2001 static symbol unresolved, even though it is

I know there are many solutions on unresolved static symbols here but I can't really find a solution to this problem.
I'm building a simple game framework as a DLL and I'm linking it with another project in my solution. When Actually it's the project I use for testing which is giving the error above not the framework itself. The code seems correct to me, I'm declaring it as a private parameter in the header file and declaring it before anything in the .cpp file.
I'm using Visual Studio 2015 if it can help somehow.
Input.h file:
class DLLEXPORT Manager{
public:
Manager();
};
class DLLEXPORT Input{
public:
static void Foo();
public:
friend class Manager;
static Manager* m_manager;
};
Input.cpp file
#include "Manager.h"
Manager* Input::m_manager = 0;
Manager::Manager(){
Input::m_manager = this;
}
PS: Sorry for the bad english.

Unresolved External Symbol C++

I have read this informative stackoverflow question regarding unresolved external symbols, but I am still not sure how to solve my issue.
Within Visual Studio 2012, I have a solution consisting of multiple projects, one of which is a static library called common. Each project that produces an executable consists of a header and associated cpp file of all global functions used throughout that specific program, called programglobals. In the process of developing one of these projects, I started duplicating some of this code from one project's programglobals to another. Now that I have completed all the projects, I want to extract the duplicate code into a associated header and cpp file within the common library, but I believe I might be referencing them incorrectly, which is producing these unresolved external symbol errors
Here is a dumbed down example of what I am currently attempting.
Common Library Files
//solutionglobals.h
void commonFunction();
//solutionglobals.cpp
void commonFunction() {
int asdf;
}
Project A Files
// programglobals.h
#include "../common/solutionglobals.h
void functionUsedInProjectA();
// programglobals.cpp
void functionUsedInProjectA() {
int x;
}
// output.h
#include "programglobals.h"
void asdfA();
// output.cpp
void asdfA() {
int x;
functionUsedInProjectA();
commonFunction();
}
Project B Files
// programglobals.h
#include "../common/solutionglobals.h
void functionUsedInProjectB();
// programglobals.cpp
void functionUsedInProjectB() {
int x;
}
// output.h
#include "programglobals.h"
void asdfB();
// output.cpp
void asdfB() {
int x;
functionUsedInProjectB();
commonFunction();
}
Any reference to commonFunction() results in an unresolved external symbol error.
Thanks!
You will have to specify in your executable projects that they reference the static lib. May be http://msdn.microsoft.com/en-us/library/vstudio/ms235627%28v=vs.110%29.aspx#uselibinapp helps (lower third of the article).
Before you can use the math routines in the static library, you must
reference it. To do this, open the shortcut menu for the MyExecRefsLib
project in Solution Explorer, and then choose References. In the
MyExecRefsLib Property Pages dialog box, expand the Common Properties
node, select Framework and References, and then choose the Add New
Reference button.
The linker cannot 'see' your function and as such thinks that it does not have an external symbol referencing it, hence the error.
You must #pragma comment(lib, [library here]) to reference the external function.
The following code can be used to reproduce this error:
[header file- test.h]:
#include "StdAfx.h"
void someOtherFunction();
void someFunction(string thisVar);
[code file- test.cpp]:
#include "StdAfx.h"
#include "test.h"
void someOtherFunction()
{
printf("Hello World!");
}
[function body for someFunction(string thisVar) is missing!]

Templated partial application call issues

For the upcoming Coursework in January, I started developing a small DirectX engine. To find out if there is a performance increase I wanted to try to not use any virtuals at all (I know that virtuals aren't all bad, but I just wanted to see if it is possible without them).
When I started playing around with a simple StateManager, it got hard to avoid virtuals, but this is my current approach:
#include <boost\function.hpp>
#include <boost\bind.hpp>
template <class Derived>
struct TBaseState {
bool update(float delta) {
return static_cast<Derived *>(this)->update(delta);
};
};
struct CTestState : TBaseState<CTestState> {
bool update(float delta) {
return true;
}
};
class StateManager
{
public:
template <class StateClass> static void setState(StateClass nextState)
{
m_funcptrUpdate = boost::bind(&TBaseState<StateClass>::update, boost::ref(nextState), _1);
}
static bool update(float delta)
{
return m_funcptrUpdate(delta);
}
protected:
private:
static boost::function<bool (float)> m_funcptrUpdate;
};
Visual Studio 2010's Intellisense seems to think everything is fine, but when I want to compile the program and test the StateManager with a very basic approach:
CTestState* t = new CTestState();
StateManager::setState(*t);
StateManager::update(0.0f);
The following error is thrown during linking phase:
error LNK2001: unresolved external symbol "private: static class boost::function<bool __cdecl(float)> StateManager::m_funcptrUpdate" (?m_funcptrUpdate#StateManager##0V?$function#$$A6A_NM#Z#boost##A)
So obviously he can't find the binded function, but how can I solve this issue? I get similar errors if I use boost::bind directly to some class. Since I am a computer science student I would also be interested in some insight or approaches without boost (e.g. bind1st, ...).
EDIT:
I was also thinking about using C++11 Variadic Templates, but one of the coursework requirements is to stick to VS2012.
Static class members need to be given storage. They're like extern variables. Add a definition to one of your .cpp files, outside of the class definition:
boost::function<bool (float)> StateManager::m_funcptrUpdate;
Also, in this code:
template <class StateClass> static void setState(StateClass nextState)
{
m_funcptrUpdate = boost::bind(&TBaseState<StateClass>::update,
boost::ref(nextState), _1);
}
You're maintaining storing a reference to the local variable nextState. That reference will be invalid after setState returns.