Define sorting method ( that use std::sort for sorting) of a templated class in dll and calling it from another project - c++

Sorry for my bad English. I have 2 projects. Project 1 is a MFC dll that contains class CMyContainer, class CEmployee. Project 2 is my main project. In project 2, I created an instance of CMyContainer of type CEmployee. Now I want to sort the container but I got an error
"error LNK2019: unresolved external symbol "bool __cdecl MyComparer(class CEmployee *,class CEmployee *)" (?MyComparer##YA_NPAVCEmployee##0#Z) referenced in function "public: void __thiscall CMyContainer<class CEmployee>::sortContainer(void)" (?sortContainer#?$CMyContainer#VCEmployee####QAEXXZ)"
How can I fix this problem?
// file MyContainer.h in project 1
#include <vector>
template <class T>
class _declspec(dllexport) CMyContainer
{
public:
CMyContainer(void);
~CMyContainer(void);
...
void sortContainer();
private:
std::vector<T*> items;
typename std::vector<T*>::iterator it;
};
template <class T> void CMyContainer<T>::sortContainer()
{
typedef bool (*comparer_t)(T*,T*);
comparer_t cmp = &MyComparer;
std::sort(items.begin(), items.end(), cmp);
}
//File Employee.h in project 1
#include "MyContainer.h"
class _declspec(dllexport) CEmployee
{
public:
CEmployee(void);
~CEmployee(void);
void setEmployeeCode(CString);
CString getEmployeeCode();
friend bool MyComparer(CEmployee*, CEmployee*);
private:
CString m_szEmployeeCode;
}
//File Employee.cpp in project 1
void CEmployee::setEmployeeCode(CString val){
m_szEmployeeCode= val;
}
CString CEmployee::getEmployeeCode(){
return m_szEmployeeCode;
}
bool MyComparer(CEmployee*pEmp1, CEmployee*pEmp2)
{
return (pEmp1->getEmployeeCode().Compare(pEmp2->getEmployeeCode())<0);
}
//File main.cpp in project 2
#include <..\Models\MyContainer.h>
#include <..\Models\Employee.h>
...
CMyContainer<CEmployee> *pListEmployee;
... // insert into pListEmployee
// sort pListEmployee
pListEmployee.sortContainer();//-> This command cause error

Try to export MyComparer from the .dll with _declspec(dllexport)

Related

I get a linking error (LINK 2019) when I try to augment a class with template

I'm trying to build a simple heap data structure for practice. When I build the version for double it works fine.
class heapt {
public:
heapt();
heapt(std::initializer_list<double> lst);
void print_heapt();
private:
int size;
int length;
double* elem; //points to root
};
Its constructors works perfectly and the heap is printed as it should. But when I try to generalize it with
template< typename Elem>
as:
template<typename Elem>
class heapt {
public:
heapt();
heapt(std::initializer_list<Elem> lst);
void print_heapt();
private:
int size;
int length;
Elem* elem; //points to root
};
for the class definition and as:
template<typename Elem>
heapt<Elem>::heapt(std::initializer_list<Elem> lst) :
size{ static_cast<int>(lst.size()) },
elem{new Elem[lst.size()]}
{
std::copy(lst.begin(), lst.end(), elem);//Now heaptify elem
build_heapt(elem, lst.size());
}
for one of the constructors used in the main function.
I get two linking errors:
LNK2019 unresolved external symbol "public: void __thiscall heapt::print_heapt(void)" (?print_heapt#?$heapt#H##QAEXXZ) referenced in function _main
LNK2019 unresolved external symbol "public: __thiscall heapt::heapt(class std::initializer_list)" (??0?$heapt#H##QAE#V?$initializer_list#H#std###Z) referenced in function _main
The main function is:
{
heapt<int> hh{ 27,12,3,13,2,4,14,5 };
std::cout << "Hello" << '\n';
hh.print_heapt();
}
EDIT: The heapt class is in the "heap.h" file and the definition for the constructor heapt<Elem>::heapt(std::initializer_list<Elem> lst) is in the "heap.cpp" class, which has #include"heap.h" as a header file. The int main function is in a file named "InSo.cpp", which also has #include"heap.h" as a header file.
In your templated class declaration you are using heapt(std::initializer_list<double> lst); but in your definition you are using std::initializer_list<Elem>. You should change the declaration to heapt(std::initializer_list<Elem> lst);
You are still missing definitions for print_heapt and build_heapt but otherwise it should compile.
EDIT: In light of you clarifying how your source files are set up, see WhozCraig's comment on your initial post. You can either include the definition of the templated class functions in a heap.hpp file, for example, and include it at the end of your heap.h, or just put them all together in one file, e.g.
// heap.h
#ifndef HEAP_H
#define HEAP_H
#include <initializer_list>
template<typename Elem>
class heapt {
public:
heapt();
heapt(std::initializer_list<Elem> lst);
void print_heapt();
private:
int size;
int length;
Elem* elem; //points to root
};
#include "heap.hpp"
#endif
//heap.hpp
#ifndef HEAP_HPP
#define HEAP_HPP
#include "heap.h"
#include <algorithm>
template<typename Elem>
heapt<Elem>::heapt(std::initializer_list<Elem> lst) :
size{ static_cast<int>(lst.size()) },
elem{ new Elem[lst.size()] }
{
std::copy(lst.begin(), lst.end(), elem);//Now heaptify elem
//build_heapt(elem, lst.size());
}
#endif

C++ Unresolved External on Class in Project [duplicate]

This question already has answers here:
Why do I get "unresolved external symbol" errors when using templates? [duplicate]
(3 answers)
Closed 3 years ago.
So I'm new to C++ and Visual Studio and I'm trying to implement a hash table using templates. I have four files: main.cpp, HashNode.h, HashTable.h, and HashTable.cpp.
main calls the HashTable constructor with a paramenter (the definition is in HashNode.h, with the implementation in the cpp file), but this throws 2 unresolved external errors: one for the called constructor, and one for what I assume to be the default constructor.
However, main also calls the HashNode constructor with no problems. HashNode has its implementation and declaration all in the HashNode.h file, but moving HashTable's implementation to its .h file didn't clear the error. So I'm very confused lol.
I'm running Visual Studio 2019, fresh install, and using the default build button to build it. It does compile and run other things (like hello world), just not this.
I've also tried adding random garbage into HashTable.cpp to see if the compiler just didn't see that it existed, but that's not the case. It also throws a compilation error then.
HashTable.h:
#pragma once
#include "HashNode.h"
template <typename T>
class HashTable
{
public:
void AddItem(int key, T item);
T* GetItem(int key);
HashTable(int buckets);
~HashTable();
int print();
private:
HashNode<T>** elements;
int buckets;
};
HashTable.cpp:
#include "HashTable.h"
#include "HashNode.h"
#include <stdexcept>
template<typename T>
HashTable<T>::HashTable(int buckets)
{
elements = new HashNode<T> * [buckets];
for (int i = 0; i < buckets; i++)
{
elements[i] = nullptr;
}
HashTable::buckets = buckets;
}
... //other methods defined below
HashNode.h
#pragma once
template <typename V>
class HashNode
{
public:
HashNode(int key, const V value) : k(key), v(value), next(nullptr) {}
int getKey () const { return k; }
V getValue() const { return v; }
HashNode* getNext() const { return next; }
void setNext(HashNode* next) { HashNode::next = next; }
void appendToChain(HashNode* last)
{
HashNode* curr = this;
while (curr->getNext() != nullptr)
{
curr = curr->getNext();
}
curr.setNext(last);
}
private:
int k;
V v;
HashNode* next;
};
Main.cpp:
#include <iostream>
#include "HashTable.h"
#include "HashNode.h"
int main()
{
std::cout << "Hello World!\n";
HashNode<int> node(1,1); //works fine
std::cout << node.getValue() << std::endl; //prints fine
HashTable<int> table(5); //throws error on compilation
}
It's probably just something stupid or that I'm blind, but here's the errors:
Error LNK1120 2 unresolved externals HashTable D:\C++\HashTable\Debug\HashTable.exe 1
Error LNK2019 unresolved external symbol "public: __thiscall HashTable<int>::HashTable<int>(int)" (??0?$HashTable#H##QAE#H#Z) referenced in function _main HashTable D:\C++\HashTable\HashTable\Main.obj 1
Error LNK2019 unresolved external symbol "public: __thiscall HashTable<int>::~HashTable<int>(void)" (??1?$HashTable#H##QAE#XZ) referenced in function _main HashTable D:\C++\HashTable\HashTable\Main.obj 1
Also, please don't hesitate to give me pointers if my code's bad. I've never really programmed anything in C++ before so any help is welcome!
You need to move the template function definitions into the header file.
A longer answer can be found here.

"unresolved external symbol" error when trying to compile C++ project [duplicate]

This question already has answers here:
Why do I get "unresolved external symbol" errors when using templates? [duplicate]
(3 answers)
Closed 7 years ago.
I am trying to implement a few classes but i got the following error when compiling the codes. I have tried to removed all the redundant codes but none of them helps. I have no idea what went wrong.
Here is the error i get when compile the code:
Severity Code Description Project File Line
Error LNK2019 unresolved external symbol "public: __thiscall FullArray<int>::FullArray<int>(unsigned int)" (??0?$FullArray#H##QAE#I#Z) referenced in function _wmain FinancialDerivatives C:\Users\Jeremy Nguyen\Documents\Visual Studio 2015\Projects\FinancialDerivatives\FinancialDerivatives\FinancialDerivatives.obj 1
Error LNK1120 2 unresolved externals FinancialDerivatives C:\Users\Jeremy Nguyen\Documents\Visual Studio 2015\Projects\FinancialDerivatives\Debug\FinancialDerivatives.exe 1
Error LNK2019 unresolved external symbol "public: virtual __thiscall FullArray<int>::~FullArray<int>(void)" (??1?$FullArray#H##UAE#XZ) referenced in function _wmain FinancialDerivatives C:\Users\Jeremy Nguyen\Documents\Visual Studio 2015\Projects\FinancialDerivatives\FinancialDerivatives\FinancialDerivatives.obj 1
FullArray.h file:
#pragma once
#include <vector>
template <class V>
class FullArray
{
private:
std::vector<V> m_vector; // Use STL vector class for storage
public:
// Constructors & destructor
FullArray();
FullArray(size_t size);
FullArray(const FullArray<V>& source);
FullArray<V>& operator = (const FullArray<V>& source);
virtual ~FullArray();
};
FullArray.cpp file:
#include "stdafx.h"
#include "FullArray.h"
template<class V>
FullArray<V>::FullArray()
{
m_vector = std::vector<V>(1); // vector object with 1 element
}
template<class V>
FullArray<V>::FullArray(size_t size)
{
m_vector = std::vector<V>(size);
}
template<class V>
FullArray<V>::FullArray(const FullArray<V>& source)
{
m_vector = source.m_vector;
}
template<class V>
FullArray<V>& FullArray<V>::operator=(const FullArray<V>& source)
{
// Exit if same object
if (this == &source) return *this;
// Call base class constructor
//ArrayStructure<V>::operator = (source);
// Copy the embedded vector
m_vector = source.m_vector;
return *this;
}
template<class V>
FullArray<V>::~FullArray()
{
}
main file:
#include "stdafx.h"
#include "FullArray.h"
int _tmain(int argc, _TCHAR* argv[])
{
FullArray<int> tmp(5);
return 0;
}
If you compile templates, the source needs to be available at any place where they are used, so include your .cpp file at the bottom of the .h file, or include the .cpp file instead of the .h file.

std::unordered_map and linker errors

I'm have some problems with compiling my new project.
Compiler outputs:
1>------ Build started: Project: IRPCore, Configuration: Debug Win32 ------
1> core.cpp
1> Creating library D:\Repo\Inter Role Play Gamemode\sa-mp-0.2-plugin-sdk\IRP\Debug\IRPCore.lib and object D:\Repo\Inter Role Play Gamemode\sa-mp-0.2-plugin-sdk\IRP\Debug\IRPCore.exp
1>core.obj : error LNK2001: unresolved external symbol "public: static class std::tr1::unordered_map<int,struct item,class std::hash<int>,struct std::equal_to<int>,class std::allocator<struct std::pair<int const ,struct item> > > core::itemCache" (?itemCache#core##2V?$unordered_map#HUitem##V?$hash#H#std##U?$equal_to#H#3#V?$allocator#U?$pair#$$CBHUitem###std###3##tr1#std##A)
1>main.obj : error LNK2001: unresolved external symbol "public: static class std::tr1::unordered_map<int,struct item,class std::hash<int>,struct std::equal_to<int>,class std::allocator<struct std::pair<int const ,struct item> > > core::itemCache" (?itemCache#core##2V?$unordered_map#HUitem##V?$hash#H#std##U?$equal_to#H#3#V?$allocator#U?$pair#$$CBHUitem###std###3##tr1#std##A)
1>D:\Repo\Inter Role Play Gamemode\sa-mp-0.2-plugin-sdk\IRP\Debug\IRPCore.dll : fatal error LNK1120: 1 unresolved externals
Here comes core.cpp
#include <iostream>
#include <unordered_map>
#include "core.h"
core::core(void)
{
}
core::~core(void)
{
}
void core::Item_Insert(int uid, item Item)
{
core::itemCache.insert(std::make_pair<int,item>(uid, Item));
return;
}
std::string core::convertNativeStringToString(AMX *amx, cell input)
{
char *string = NULL;
amx_StrParam(amx, input, string);
return string ? string : "";
}
Should I link some more libs or so?
Thanks in advance.
Edit: Here comes core definition from core.h
class core
{
public:
static std::unordered_map<int, item> itemCache;
core(void);
~core(void);
static void Item_Insert(int uid, item Item);
static std::string convertNativeStringToString(AMX *amx, cell input);
private:
};
Add a definition of core::itemCache to core.cpp. In general, static data members of classes are declared in the class definition and defined in a source file.
As #Pete Becker is saying, put this at the top of the cpp:
std::unordered_map<int, item> core::itemCache;
in addition to the
static std::unordered_map<int, item> itemCache;
already in the .h.

Link error using std::vector

I'm having a problem with a vector declaration.
Here's the code:
.h
#ifndef ANIMATEDSPRITE_H_
#define ANIMATEDSPRITE_H_
#include "Sprite.h"
#include <vector>
//using namespace std;
class AnimatedSprite //abstract class to point sprites
{
public:
AnimatedSprite();
~AnimatedSprite();
//gets and sets
Sprite GetMySprite(int _index);
void SetSpriteToList(Sprite _sprite);
int GetState() const;
void SetState(int _state);
//other
private:
std::vector<Sprite> spriteList;
int state; //estado que esse sprite representa (parado esquerda, andando direita, etc)
};
#endif
.cpp
#include "AnimatedSprite.h"
AnimatedSprite::AnimatedSprite()
{
spriteList.clear();
state = NULL;
}
AnimatedSprite::~AnimatedSprite()
{
}
Sprite AnimatedSprite::GetMySprite(int _index)
{
return spriteList[_index];
}
void AnimatedSprite::SetSpriteToList( Sprite _sprite )
{
//Sprite* temp = new Sprite(1,2);
spriteList.push_back(_sprite);
}
int AnimatedSprite::GetState() const
{
return state;
}
void AnimatedSprite::SetState( int _state )
{
state = _state;
}
But I'm getting 2 errors:
Error 1 error LNK2019: unresolved external symbol imp_CrtDbgReportW referenced in function "public: class Sprite & __thiscall std::vector >::operator[](unsigned int)" (??A?$vector#VSprite##V?$allocator#VSprite###std###std##QAEAAVSprite##I#Z) AnimatedSprite.obj
Error 2 fatal error LNK1120: 1 unresolved externals C:\DevProjects\SDLSkeleton\Debug\SDLSkeleton.exe
I've found a solution removing the _DEBUG from the Preprocessor Definitions, but it seems kinda wrong to do that.
Is it the right solution? What's the consequence of removing it?
In the book and documentations I've checked it should be just a common variable declaration, but this errors showed up.
Thanks.
This is because your build is inconsistent: you define _DEBUG macro, but link with release CRT version (/MD). So either remove _DEBUG, or select /MDd option.