ThreadPool class: can't pass the args straight - c++

I have a Thread pool of the type that can be found here.
I try doing the following:
/* Allocate a ThreadPool */
shared_ptr<SpinTools::ThreadPool> pool(new SpinTools::ThreadPool(4));
/* Start processing each image in Core container */
for (int img_idx = 0; img_idx < num_images; img_idx++) {
pool->enqueue(_worker_task, img_idx, _args, _stats);
}
My worker task has the following prototype:
void _worker_task(int img_idx, ProcessorArgs &args, Stats &stats)
however this won't compile and MSVC displays the error
Error 14 error LNK2019: unresolved external symbol "public: class std::future<void> __cdecl ThreadPool::enqueue<void (__cdecl&)(int,struct ProcessorArgs,struct SpinCore::Features::Stats &),int &,struct Sift::ProcessorArgs &,struct SpinCore::Features::Stats &>(void (__cdecl&)(int,struct ProcessorArgs,struct SpinCore::Features::Stats &),int &,struct ProcessorArgs &,struct SpinCore::Features::Stats &)" (??$enqueue#A6AXHUProcessorArgs#Sift##AEAUStats#Features#SpinCore###ZAEAHAEAU12#AEAU345##ThreadPool#SpinTools##QEAA?AV?$future#X#std##A6AXHUProcessorArgs#Sift##AEAUStats#Features#SpinCore###ZAEAHAEAU45#1#Z) referenced in function "public: virtual void __cdecl Sift::process(void)" (?process#Sift##UEAAXXZ)
Edit: adding the header for ThreadPool::enqueue for completness:
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>;

You need to place the implementation of ThreadPool::enqueue in the header. MSVC can't generate the implementation if it's in .cpp file only (or at least earlier versions could not)

Related

unresolved external symbol "__declspec(dllimport)"

I'm trying to code a little plugin for bakkesmod because I'm pissing myself off.
I watched the only 2 video that exists on this topic but ... it doesn't work and I have this error for each void - >> Severity Code Description Project File Line Suppression State
Error LNK2001 unresolved external symbol "__declspec(dllimport) public: void __thiscall GameWrapper::HookEvent(class std::basic_string<char,struct std::char_traits,class std::allocator >,class std::function<void __cdecl(class std::basic_string<char,struct std::char_traits,class std::allocator >)>)" (_imp?HookEvent#GameWrapper##QAEXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V?$function#$$A6AXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z#3##Z) TagName C:\Users\leodu\source\repos\TagName\TagName\TrollTagName.obj 1
here is my code.
TroolTagName.cpp (not judge the name)
#include "TrollTagName.h"
BAKKESMOD_PLUGIN(TroolTagName, "Trool Tag Name", "1.0", PERMISSION_ALL)
void TroolTagName::onLoad()
{
this->Log("This is my first Bakkesmod Plugin");
this->LoadHooks();
}
void TroolTagName::onUnload()
{
}
void TroolTagName::LoadHooks()
{
gameWrapper->HookEvent("Function TAGame.GameEvent_Soccar_TA.EventMatchEnded", std::bind(&TroolTagName::GameEndedEvent, this, std::placeholders::_1));
gameWrapper->HookEvent("Function TAGame.AchievementManager_TA.HandleMatchEnded", std::bind(&TroolTagName::GameEndedEvent, this, std::placeholders::_1));
}
void TroolTagName::GameEndedEvent(std::string name)
{
cvarManager->executeCommand("load_freeplay");
}
void TroolTagName::Log(std::string msg)
{
cvarManager->log("TroolTagName: " + msg);
}
TroolTagName.h
#include "bakkesmod\plugin\bakkesmodplugin.h"
#pragma comment(lib, "pluginsdk.lib")
class TroolTagName : public BakkesMod::Plugin::BakkesModPlugin
{
public:
virtual void onLoad();
virtual void onUnload();
void LoadHooks();
void GameEndedEvent(std::string name);
private:
void Log(std::string msg);
};
The project and a Dynamic-library dll project.
I tried adding __declspec (dllexport) before void but ... I got this error - >> redefinition; different linkage and I found nothing for this error so I am blocked :(

Unresolved external symbol in only a few methods (static or shared library)

This is driving me nuts, using MSVC14.1 I am making a library A to be used in another shared library B. It does not matter if the library A is static or shared, I always end up with 3 unresolved external symbols as such :
[build] GroomDeformer.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: static class avPoly::PolyMesh __cdecl avPoly::PolyMesh::create(class std::vector<struct glm::vec<3,float,0>,class std::allocator<struct glm::vec<3,float,0> > > const &,class std::vector<unsigned int,class std::allocator<unsigned int> > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &)" (__imp_?create#PolyMesh#avPoly##SA?AV12#AEBV?$vector#U?$vec#$02M$0A##glm##V?$allocator#U?$vec#$02M$0A##glm###std###std##AEBV?$vector#IV?$allocator#I#std###4#AEBV?$vector#_KV?$allocator#_K#std###4##Z) referenced in function "public: void __cdecl avGroomCore::GroomDeformer::ConstructMesh(class std::vector<struct glm::vec<3,float,0>,class std::allocator<struct glm::vec<3,float,0> > > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class std::vector<unsigned int,class std::allocator<unsigned int> > const &)" (?ConstructMesh#GroomDeformer#avGroomCore##QEAAXAEBV?$vector#U?$vec#$02M$0A##glm##V?$allocator#U?$vec#$02M$0A##glm###std###std##AEBV?$vector#_KV?$allocator#_K#std###4#AEBV?$vector#IV?$allocator#I#std###4##Z) [C:\Users\tufto\PycharmProjects\avgroom\build\src\core\Core.vcxproj]
[build] GroomDeformer.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: class avPoly::FaceLocation __cdecl avPoly::PolyMesh::getClosestLocation(struct glm::vec<3,float,0> const &)" (__imp_?getClosestLocation#PolyMesh#avPoly##QEAA?AVFaceLocation#2#AEBU?$vec#$02M$0A##glm###Z) referenced in function "public: void __cdecl avGroomCore::GroomDeformer::DeformGroom(void)" (?DeformGroom#GroomDeformer#avGroomCore##QEAAXXZ) [C:\Users\tufto\PycharmProjects\avgroom\build\src\core\Core.vcxproj]
[build] GroomDeformer.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: struct glm::vec<3,float,0> __cdecl avPoly::PolyMesh::getAttributeValueFromLocation(class avPoly::FaceLocation const &,class avPoly::Attribute<struct glm::vec<3,float,0> > &)" (__imp_?getAttributeValueFromLocation#PolyMesh#avPoly##QEAA?AU?$vec#$02M$0A##glm##AEBVFaceLocation#2#AEAV?$Attribute#U?$vec#$02M$0A##glm###2##Z) referenced in function "public: void __cdecl avGroomCore::GroomDeformer::DeformGroom(void)" (?DeformGroom#GroomDeformer#avGroomCore##QEAAXXZ) [C:\Users\tufto\PycharmProjects\avgroom\build\src\core\Core.vcxproj]
I do not know what to do at this stage. I looked into the symbols from dumpbin and i do get the signatures, for example :
__imp_?create#PolyMesh#avPoly##SA?AV12#AEBV?$vector#U?$tvec3#M$0A##glm##V?$allocator#U?$tvec3#M$0A##glm###std###std##AEBV?$vector#IV?$allocator#I#std###4#AEBV?$vector#_KV?$allocator#_K#std###4##Z
The only thing i can notice is this has "tvec3" instead of just "vec" in the error signature. I think this refers to a typedef i have to GLM for library A such as :
typedef glm::vec3 Vector3;
typedef std::vector<Vector3> Vector3Array;
Any ideas or guidelines on how i could debug this ? I've tried all I can think off and can't put my finger on it. The worst part is that in the library A project i have another mini executable to test it that links just fine... (all using CMake). Both CMake configs are the same.
Here are the method signatures in the header file for these :
AVPOLYLIB_API
static PolyMesh create(Vector3Array const &positions, UIntArray const &faceVertexCounts, IndexArray const &faceVertexIndices);
AVPOLYLIB_API
FaceLocation getClosestLocation(Vector3 const &point);
AVPOLYLIB_API
Vector3 getAttributeValueFromLocation(FaceLocation const & location, Attribute<Vector3> &attribute);
DLL Export is done as follows :
#ifdef AVPOLYLIB_STATIC
#define AVPOLYLIB_API
#else
#ifdef AVPOLYLIB_EXPORTS
#define AVPOLYLIB_API __declspec(dllexport)
#else
#define AVPOLYLIB_API __declspec(dllimport)
#endif
#endif
The types used in these methods are declared like this (inside the library namespace):
class FaceLocation {
public:
Index triangleId;
Vector3 barycentricCoordinates;
};
typedef std::vector<Vector3> Vector3Array;
typedef std::vector<Index> IndexArray;
typedef std::vector<unsigned int> UIntArray;
Solved it ! It was silly : there was a problem with the glm headers as they where submodules in both libraries but for some reason where not version matching. So i did have a wrong signature in the exported symbols. Using the headers in the same folder solved the issue.

c++ optional/default argument

I have defined a method with an optional/defaulted last argument called noAutoResolve as follows:
typedef std::shared_ptr<IMessage> TMessagePtr;
class NetworkService : public IConnectionManagerDelegate, public net::IStreamDelegate
{
public:
void send_message(std::string identity, msg::TMessagePtr msg, QObject* window, std::function<void(int, std::shared_ptr<msg::IMessage> msg)> fn, bool noAutoResolve = false);
}
and later:
void NetworkService::send_message(std::string endpoint, msg::TMessagePtr msg, QObject* window, std::function<void(int res, std::shared_ptr<msg::IMessage> msg)> fn, bool noAutoResolve)
{
}
The linker is now unhappy about unresolved externals in the following line where I intentionally omitted the last argument:
service_->send_message(endpoint_, msg, this, [this](int result, msg::TMessagePtr msg){
// .....
});
Is that not possible in c++?
Error LNK1120 1 unresolved externals QTServer QTServer.exe 1
Error LNK2019 unresolved external symbol "public: void __thiscall NetworkService::send_message(class std::basic_string,class std::allocator >,class std::shared_ptr,class QObject *,class std::function)>)" (?send_message#NetworkService##QAEXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V?$shared_ptr#UIMessage#msg###3#PAVQObject##V?$function#$$A6AXHV?$shared_ptr#UIMessage#msg###std###Z#3##Z) referenced in function "public: void __thiscall QTWindow::ExecuteCommand(void)" (?ExecuteCommand#QTWindow##QAEXXZ) QTServer QTWindow.obj 1
The fn parameter of your function is type of std::function<void(int, std::shared_ptr<msg::IMessage> msg)>. However, the lambda you are passing is:
[this](int result, msg::TMessagePtr msg){
// .....
}
This function has the signature of void(int, msg::TMessagePtr), so if there is no conversion from std::shared_ptr<msg::IMessage> to msg::TMessagePtr, the code cannot compile.
Your problem is therefore not about the optional parameter. For a quick fix, if you have access to a C++14 compiler, try getting the lambda parameters as auto:
[this](auto result, auto msg){
// .....
}

C++ Template/Generics error

I have a simple function setup to check if a value is in a std::vector, and I would like to use a 'Template' to beable to use the function with all classes.
Some definitions
std::vector<ItemID_t> *spareItems;
ItemID_t newItem;//note this is an enumeration value
The function works perfectly if I call with
bool b = !vectorContains(*spareItems,newItem);
and the function looks like
bool vectorContains(std::vector<ItemID_t> &vector,const ItemID_t& value){
return std::find(vector.begin(), vector.end(), value)!=vector.end();
}
but if I try to implement generics with the call
bool b = !vectorContains<ItemID_t>(*spareItems,newItem);
and the function definition
template <class T>
bool vectorContains(std::vector<T> &vector,const T& value){
return std::find(vector.begin(), vector.end(), value)!=vector.end();
}
It fails in the second example and gives me this linker error
error LNK2019: unresolved external symbol "bool __cdecl turtle::vectorContains<enum turtle::ItemID_t>(class std::vector<enum turtle::ItemID_t,class std::allocator<enum turtle::ItemID_t> > &,enum turtle::ItemID_t const &)" (??$vectorContains#W4ItemID_t#turtle###turtle##YA_NAAV?$vector#W4ItemID_t#turtle##V?$allocator#W4ItemID_t#turtle###std###std##ABW4ItemID_t#0##Z) referenced in function "public: void __thiscall turtle::Barracks::swapItems(int,enum turtle::ItemID_t)" (?swapItems#Barracks#turtle##QAEXHW4ItemID_t#2##Z)
Thank you

C++ Packet Builder with Templates

PacketBuilder is a little Class which allow to write into a char* array. The Append Functions:
template <class T>
void PacketBuilder::Append(const T value)
{
memcpy((&m_Buffer) + m_Index, (const void*) &value, sizeof(T));
m_Index += sizeof(T);
}
Compiling without errors. If I call Append and use T as unsigned short (WORD). It works great. If I use T as unsigned char. I get an Linker Error.
m_Builder.Append<unsigned char>(0x01); // Error: LNK1120
m_Builder.Append<unsigned short>(0x0001); // Works
Error from VS2010 (sry i got german vs2010):
error LNK2019: Verweis auf nicht
aufgelöstes externes Symbol ""public:
void __thiscall
PacketBuilder::Append(unsigned char)"
(??$Append#E#PacketBuilder##QAEXE#Z)"
in Funktion ""public: void __thiscall
Client::DoHandshake(void)"
(?DoHandshake#Client##QAEXXZ)".
1>C:\XXX\C++\SilkroadEmu\Debug\LoginServer.exe
: fatal error LNK1120: 1 nicht
aufgelöste externe Verweise.
Translated to English:
error LNK2019: Unresolved external
symbol ""public: void __thiscall
PacketBuilder::Append(unsigned char)"
(??$Append#E#PacketBuilder##QAEXE#Z)"
in Function ""public: void __thiscall
Client::DoHandshake(void)"
(?DoHandshake#Client##QAEXXZ)".
1>C:\XXX\C++\SilkroadEmu\Debug\LoginServer.exe
: fatal error LNK1120: 1 unsresolved
external symbol.
Put the method definition in the header (hpp file), not in the implementation (cpp) file.
Your PacketBuilder is not a class template, as far as I can see. PacketBuilder::Append is however a template method, which requires that it's definition must be visible at any point of instantiation of this method. The only really safe way to assure this is to put the complete definition of this method template into the header file:
class PacketBuilder {
// declarations of non-template members
public:
template <class T>
void Append(const T value)
{
memcpy((&m_Buffer) + m_Index, (const void*) &value, sizeof(T));
m_Index += sizeof(T);
}
};