I am trying to create a class library dll that exports a template class. I have a local version of the same class and it must be coincidental, but it works correctly. I know this doesn't really mean much, clearly something is wrong.
The exported template class in the library dll is:
template <class CcmBlock>
class CCMSHARED_EXPORT CcmFilter
{
public:
CcmFilter()
{
mBlock = nullptr;
////mBlockList = new std::list<CcmBlock*>();
}
void add(CcmFrame* frame)
{
if (frame == nullptr)
return;
mBlock = new CcmBlock(
frame->getFrameData(),
frame->getSampleRate(),
0xFFFFFFFF,
frame->getBlockSize(),
frame->getDomain()
);
mBlockList->push_back(aBlock);
}
CcmBlock* get()
{
return mBlock;
}
private:
CcmBlock* mBlock;
////std::list<CcmBlock*>* mBlockList;
};
On the application side:
CcmFilter<FooBlock>* oneFilter = new CcmFilter<FooBlock>();
//Filter<Block>* filter = new Filter<Block>();
CcmFrame* frame = new CcmFrame(0, 50000, 40, 1024, Domain::Time);
oneFilter->add(frame);
CcmBlock* block = oneFilter->get();
FooBlock* fooBlock = dynamic_cast<FooBlock*>(block);
if (fooBlock == nullptr)
{ //Report Error }
else
{ // Do the work}
and the FooBlock class is derived from CcmBlock as follows:
class FooBlock : public CcmBlock
{
public:
FooBlock(int* ipblock, DWORD dwSampleRate, DWORD dwMicrophoneIndex, DWORD dwBlockSize, Domain domain);
void process();
};
The library compiles and builds the dll. When I attempt to build the application I get messages:
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl CcmFilter::CcmFilter(void)" (__imp_??0?$CcmFilter#VFooBlock####QEAA#XZ) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow##QEAA#PEAVQWidget###Z)
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl CcmFilter::add(class CcmFrame *)" (__imp_?add#?$CcmFilter#VFooBlock####QEAAXPEAVCcmFrame###Z) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow##QEAA#PEAVQWidget###Z)
DLL-s are loaded at runtime, while templates are instantiated at compile time.
A work-around which is not ideal but might work for a very limited use case is to explicitly instantiate a template somewhere after their declaration. That is, add something like:
template class CcmFilter<FooBlock>;
For details, see https://msdn.microsoft.com/en-us/library/by56e477(VS.80).aspx
Just do not use declspec. But in your case template will be compiled each time when you include it in *.cpp file. It wont be exported.
In order to export some well-known implementations of your template you probably should use template explicit instantiation definitions in tandem with __declspec(export).
Related
I have a class like
template <class T>
class LinkedListItem
{
public:
LinkedListItem(T value);
LinkedListItem(const LinkedListItem<T>& rhs);
T getValue(void);
LinkedListItem<T>& getNext(void);
void setNext(LinkedListItem<T>& next);
LinkedListItem<T>& operator=(const LinkedListItem<T>& rhs);
~LinkedListItem();
private:
T _value;
LinkedListItem& _next;
};
I am trying to write a unit test like
TEST_CLASS(LinkedListUnitTests)
{
public:
TEST_METHOD(Add_to_An_Empty_Linked_List)
{
LinkedListItem<int> item(1);
}
//private:
};
When I try to just build the above code I get the ugly error -
error LNK2019: unresolved external symbol "public: __thiscall cpp::libraries::datastructures::LinkedListItem::LinkedListItem(int)" (??0?$LinkedListItem#H#datastructures#libraries#cpp##QAE#H#Z) referenced in function "public: void __thiscall CppLibrariesTests::LinkedListUnitTests::Add_to_An_Empty_Linked_List(void)" (?Add_to_An_Empty_Linked_List#LinkedListUnitTests#CppLibrariesTests##QAEXXZ)
I am using Visual Studio 2012.
Interestingly, If I add template in the unit test class like below the compile error goes away but the tests are not discovered and I can't run them.
template<class T>
TEST_CLASS(LinkedListUnitTests){..}
I am trying to pick up C++ after a long time so I won't be surprised if I am doing something very stupid. Any thoughts anyone?
Templates must ideally be implemented inline. Second pass of compiler cannot re use the CPP file that has the implementation. Or, you need to #include the CPP file also.
Refer this article
Im working on a project using Qt/C++ originally compiled with MinGW64 (gcc 4.8). I decided to "port" it to MSVC2013, since I need to use some Windows API functions that doesn't work well in MinGW, but right now I'm stuck at this error:
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "public: void __cdecl IMLoginView::clearFieldPass(void)" (?clearFieldPass#IMLoginView##QEAAXXZ) referenced in function "public: void __cdecl MainWindow::showConnectionErrorDialog(void)" (?showConnectionErrorDialog#MainWindow##QEAAXXZ)
imingestinglist.obj:-1: error: LNK2019: unresolved external symbol "public: static class QString __cdecl IMStorageSystem::getLogDir(void)" (?getLogDir#IMStorageSystem##SA?AVQString##XZ) referenced in function "private: class QList<int> __cdecl IMIngestingList::loadList(void)" (?loadList#IMIngestingList##AEAA?AV?$QList#H##XZ)
moc_imloginview.obj:-1: error: LNK2019: unresolved external symbol "public: void __cdecl IMLoginView::login(void)" (?login#IMLoginView##QEAAXXZ) referenced in function "private: static void __cdecl IMLoginView::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void * *)" (?qt_static_metacall#IMLoginView##CAXPEAVQObject##W4Call#QMetaObject##HPEAPEAX#Z)
moc_imloginview.obj:-1: error: LNK2019: unresolved external symbol "public: void __cdecl IMLoginView::handleError(enum ALFRED_ACCESS_ERROR)" (?handleError#IMLoginView##QEAAXW4ALFRED_ACCESS_ERROR###Z) referenced in function "private: static void __cdecl IMLoginView::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void * *)" (?qt_static_metacall#IMLoginView##CAXPEAVQObject##W4Call#QMetaObject##HPEAPEAX#Z)
moc_imloginview.obj:-1: error: LNK2019: unresolved external symbol "public: void __cdecl IMLoginView::userDisconnected(void)" (?userDisconnected#IMLoginView##QEAAXXZ) referenced in function "private: static void __cdecl IMLoginView::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void * *)"
The problem is: These methods aren't part of some external library, but part of the project itself. And I already triple checked that they are implemented. They aren't part of any template class either, but normal classes, and the log says the cpp files are being compiled. The same project links just fine with MinGW64.
I'm currently using Qt Creator 3.3.2 and QT 5.3.2.
What can be happening?
EDIT:
I Can't show much code, since its a closed-source project, but I can at least show the header and implementation layout of the methods:
imloginview.h:
class IMLoginView : public QWidget
{
Q_OBJECT
public:
explicit IMLoginView(QWidget *parent = 0);
void clearFieldPass();
~IMLoginView();
private:
//Lots of attributes
void configureComponents();
void keyPressEvent(QKeyEvent *event);
signals:
public slots:
void login();
void handleError(ALFRED_ACCESS_ERROR error);
void userDisconnected();
}
imloginview.cpp:
IMLoginView::IMLoginView(QWidget *parent) : //lots of initializations here
{
//Implementation
}
IMLoginView::~IMLoginView()
{
}
void IMLoginView::clearFieldPass()
{
//implementation
}
void IMLoginView::configureComponents()
{
//Implementation
}
void IMLoginView::keyPressEvent(QKeyEvent *event)
{
//implementation
}
void IMLoginView::login()
{
//implementation
}
void IMLoginView::handleError(ALFRED_ACCESS_ERROR error)
{
//implementation
}
void IMLoginView::userDisconnected()
{
//implementation
}
I'm sorry I really can't provide the actual method code, but its closed-source. =/
1>main.obj : error LNK2019: unresolved external symbol "public: virtual bool __thiscall LinkedSortedList<int>::getfirst(int &)" (?getfirst#?$LinkedSortedList#H##UAE_NAAH#Z) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall LinkedSortedList<int>::clear(void)" (?clear#?$LinkedSortedList#H##UAEXXZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall LinkedSortedList<int>::print(void)const " (?print#?$LinkedSortedList#H##UBEXXZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: virtual bool __thiscall LinkedSortedList<int>::insert(int)" (?insert#?$LinkedSortedList#H##UAE_NH#Z) referenced in function _main
1>main.obj : error LNK2001: unresolved external symbol "public: virtual bool __thiscall LinkedSortedList<int>::find(int)const " (?find#?$LinkedSortedList#H##UBE_NH#Z)
1>main.obj : error LNK2001: unresolved external symbol "public: virtual int __thiscall LinkedSortedList<int>::size(void)const " (?size#?$LinkedSortedList#H##UBEHXZ)
1>c:\users\chris\documents\visual studio 2010\Projects\lab0\Debug\lab0.exe : fatal error LNK1120: 6 unresolved externals
This is what I recieve when trying to compile my code. I've narrowed it down to (i believe) this section of code here:
#ifndef _LinkedSortedListClass_
#define _LinkedSortedListClass_
#include "LinkedNode.h"
#include "SortedList.h"
template <class Elm>
class LinkedSortedList: public SortedList<int> {
public:
void clear();
bool insert(Elm newvalue);
bool getfirst(Elm &returnvalue);
void print() const;
bool find(Elm searchvalue) const;
int size() const;
private:
LinkedNode<Elm>* head;
};
#endif
This is the child class of the SortedList, which is this, in case it's needed..
#ifndef _SortedListClass_
#define _SortedListClass_
template <class Elm> class SortedList {
public:
// -------------------------------------------------------------------
// Pure virtual functions -- you must implement each of the following
// functions in your implementation:
// -------------------------------------------------------------------
// Clear the list. Free any dynamic storage.
virtual void clear() = 0;
// Insert a value into the list. Return true if successful, false
// if failure.
virtual bool insert(Elm newvalue) = 0;
// Get AND DELETE the first element of the list, placing it into the
// return variable "value". If the list is empty, return false, otherwise
// return true.
virtual bool getfirst(Elm &returnvalue) = 0;
// Print out the entire list to cout. Print an appropriate message
// if the list is empty. Note: the "const" keyword indicates that
// this function cannot change the contents of the list.
virtual void print() const = 0;
// Check to see if "value" is in the list. If it is found in the list,
// return true, otherwise return false. Like print(), this function is
// declared with the "const" keyword, and so cannot change the contents
// of the list.
virtual bool find(Elm searchvalue) const = 0;
// Return the number of items in the list
virtual int size() const = 0;
};
#endif
Thanks so much for any help; our last class taught us nothing of inheritance, but this is project #1 for this class, without being taught inheritance here either, so this is all touch and go for me, despite what I managed to look up on Google.
Your methods aren't defined. So the linker is complaining because it can't link to their definitions.
Maybe it helps if you placed the definitions of your functions in your header file. This makes it easier for the compiler to resolve these external symbols.
I hope this will help.
Regards,
Philinator
Ok, I have defined the template class, which compiles as expected, when I implement this class in a function of the CMainFrame of the application and compile it, I receive unresolved linking errors.
void CMainFrame::OnFunc()
{
CTestList<CMyClass> list;
}
The linking errors:
1>mainfrm.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall CTestList<class CMyClass>::~CTestList<class CMyClass>(void)" (??1?$CTestList#VCWnd####UAE#XZ) referenced in function "protected: void __thiscall CMainFrame::OnFunc(void)" (?OnFunc#CMainFrame##IAEXXZ)
1>mainfrm.obj : error LNK2019: unresolved external symbol "public: __thiscall CTestList<class CMyClass>::CTestList<class CMyClass>(void)" (??0?$CTestList#VCWnd####QAE#XZ) referenced in function "protected: void __thiscall CMainFrame::OnFunc(void)" (?OnFunc#CMainFrame##IAEXXZ)
I've checked all the obvious missing headers, undefined functions, etc, but still it throws these errors at me, the files are all part of the main application and are not in static/shared libs, as this is the error I would expect if i'd done so..
Here is the basic definition of the template class cut right down, I've followed what I believe to be the correct path in constructing the class, and all my research seems to suggest its correct.
Really need to get this nailed ASAP, so if you guys & girls could help I would be very grateful.
Cheers,
DIGGIDY
/////////////////////////////////////////////////////////////////////////////
// CTestList class
template <class T>
class CTestList : public CMDIChildWndEx
{
//DECLARE_DYNAMIC(CTestList<T>)
public:
CTestList();
virtual ~CTestList();
protected:
// Generated message map functions
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
// CTestList
//IMPLEMENT_DYNCREATE(CTestList<SDCM_OBJECT_TYPE>, CMDIChildWndEx)
template <class T>
CTestList<T>::CTestList()
{
}
template <class T>
CTestList<T>::~CTestList()
{
}
BEGIN_TEMPLATE_MESSAGE_MAP(CTestList, T, CMDIChildWndEx)
ON_WM_CREATE()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTestList message handlers
template <class T>
int CTestList<T>::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if ( CMDIChildWndEx::OnCreate(lpCreateStruct) == -1 )
return -1;
// this removes the crappy un-drawn client edge on screen
ModifyStyleEx(WS_EX_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE);
return 0;
}
Your template code is not inlined in the header file. When the template class cpp file is being compiled the compiler doesn't know what instances of T will be required. When your main file is being compiled and you need to instantiate a CTestList the compiler only has the template header file. You need to add a force explicite template instantiation to your template .cpp file - so at the moment this is compiled it will generation the correct CMyClass instantiation of the template.
So, I have an abstract class Panel and an implementation of it MyPanel. They look similar to this:
class Panel : public QWidget
{
public:
Panel(QWidget* parent = 0) = 0;
virtual ~Panel() = 0;
// but wait, there's more!!
};
class MyPanel : public Panel
{
public:
MyPanel(QWidget* parent = 0);
~MyPanel() {}; // nothing to do here
};
MyPanel::MyPanel(QWidget* parent) :
Panel(parent)
{
// you must construct additional pylons
}
I'm getting linker errors for the constructor/destructor from VC++
error LNK2019: unresolved external symbol "public: virtual __thiscall Panel::~Panel(void)" (??1Panel##UAE#XZ) referenced in function "public: virtual __thiscall MyPanel::~MyPanel(void)" (??1MyPanel##UAE#XZ) mypanel.obj
error LNK2019: unresolved external symbol "public: __thiscall Panel::Panel(class QWidget *)" (??0Panel##QAE#PAVQWidget###Z) referenced in function "public: __thiscall MyPanel::MyPanel(class QWidget *)" (??0MyPanel##QAE#PAVQWidget###Z) mypanel.obj
Why am I getting this linker error?
--- THE ANSWER ---
class Panel : public QWidget
{
public:
Panel(QWidget* parent = 0) : QWidget(parent) {};
virtual ~Panel() {};
// but wait, there's more!!
};
I thought I had tried this before lunch. Turns out I was wrong.
there is no such thing like virtual constructor.
You still should provide implementation of destructor.
Purely virtual destructors still need to have an implementation.
To expand on that a bit:
The destructor of a class will always be called if any instance of a subclass gets destructed, so it needs to have an implementation. (Basically the only effect of making a destructor purely virtual is that it prevents instanatiation of the class).
As for the constructor: You're making it purely virtual (which I don't see any reason for doing), but then you explicitly call it from the subclass's constructor.