LINK2019 Error rebuilding library with /MTd setting instead of /MDd - visual-studio

I know it was discussed in length many times already, but my case has some particular condition I don't know how to address properly.
Library with /MDd solution builds OK. But it is not what the application needs as it requires /MT(d) version.
Now, I've changed the compiler options to /MTd, resolved some of the external projects dependencies, but still getting this:
Error LNK2019 unresolved external symbol "bool __cdecl std::uncaught_exception(void)" (?uncaught_exception#std##YA_NXZ) referenced in function "public: __cdecl std::basic_ostream<char,struct std::char_traits<char> >::sentry::~sentry(void)" (??1sentry#?$basic_ostream#DU?$char_traits#D#std###std##QEAA#XZ) vcruntime140 ..\vcruntime140 ..\vcruntime140\log.obj
log.h is just this:
#ifndef LOG_H
#define LOG_H
#include <string>
namespace hooks {
/** Prints message to the file only if debug mode setting is enabled. */
void logDebug(const std::string& logFile, const std::string& message);
/** Prints message to the file. */
void logError(const std::string& logFile, const std::string& message);
} // namespace hooks
#endif // LOG_H
log.cpp
#include "log.h"
#include <chrono>
#include <ctime>
#include <fstream>
#include <iomanip>
namespace hooks {
static void logAction(const std::string& logFile, const std::string& message)
{
using namespace std::chrono;
std::ofstream file(logFile.c_str(), std::ios_base::app);
const std::time_t time{std::time(nullptr)};
const std::tm tm = *std::localtime(&time);
file << "[" << std::put_time(&tm, "%c") << "] " << message << "\n";
}
void logDebug(const std::string& logFile, const std::string& message)
{
logAction(logFile, message);
}
void logError(const std::string& logFile, const std::string& message)
{
logAction(logFile, message);
}
} // namespace hooks
hooks.h
#ifndef HOOKS_H
#define HOOKS_H
#include <string>
#include <utility>
#include <vector>
namespace hooks {
using HookInfo = std::pair<void**, void*>;
using Hooks = std::vector<HookInfo>;
/** Returns array of hooks to setup. */
Hooks getHooks();
Hooks getVftableHooks();
} // namespace hooks
#endif // HOOKS_H
hooks.cpp
#include "hooks.h"
namespace hooks {
Hooks getHooks()
{
Hooks hooks;
return hooks;
}
Hooks getVftableHooks()
{
Hooks hooks;
return hooks;
}
} // namespace hooks
Any idea of how to resolve it?

Found solution, the only remaining issue is actually unrelated to the above. The above errors are resolved in the following way:
Adding MSVCPRTD.LIB to the additional libraries link seem to elliminate the problems with LINK2019.
The problem was happening since some of the standard library functions defined in that lib were not loaded. I've realised it by checking the error message and googling of which function definitions are missing and which library they belong to.
But now there is a problem with MSVCPRTD.LIB as it is a dynamic and not a static library according to Microsoft docs: https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-160
The problem with MSVCPRTD.LIB can be addressed by loading libcmtd.lib instead, which is the /MTd version of the same librari(es).

Related

C++11 linker error VS17

#include <iostream>
#include <fstream>
#include <type_traits>
#include <Windows.h>
#include "abase.h"
using namespace std;
class Storage {
string _path;
public:
Storage(string path);
~Storage() = default;
template <typename T >
bool writeFile(string fileName,
typename enable_if<is_base_of<ABase, T>::value, T >::type* data);
}
Definition...
#include "storage.h"
Storage::Storage(string path)
{
this->_path = path;
}
template <typename T >
bool Storage::writeFile(string fileName,
typename enable_if<is_base_of<ABase, T>::value, T >::type* data){
return true;
}
Im still getting error by Linker:
LNK2019 unresolved external symbol "public: bool __thiscall
Storage::writeFile(class std::basic_string,class std::allocator >,class AFile*)"
(??$writeFile#VAFile###Storage##QAE_NV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##PAVAFile###Z)
referenced in function _main
Why am i getting it if code is looking right. Its generic definition of method in a class and Im trying to constrain class type passing to the method.
And the AFile is inherited from ABase.
ABase is abstract class.
Simple usage in main:
Storage* s = new Storage("C:\\aPath...");
AFile* afile = new AFile();
s->writeFile<AFile>("a.txt", afile);
To solve your linking error you can explicitly instantiate[1] your template member function in the Storage.cpp like this:
template
bool Storage::writeFile<AFile>(string fileName,
enable_if<is_base_of<ABase, AFile>::value, AFile>::type* data);
so the compiler creates the function and the linker can find.
It's better to move the definitions in the header file - Why can templates only be implemented in the header file?.

Qt boost serialize compile errors on simple implementation

Platform specifics:
Fedora 21
g++ 4.9.2-6
Here's the error ....
$ g++ -c kabi-serial.cpp -lboost_serialization
kabi-serial.cpp: In function ‘void boost::serialization::kb_write_list()’:
kabi-serial.cpp:41:13: error: expected ‘;’ before ‘oa’
serialize oa(ofs);
kabi-serial.cpp:41:20: error: statement cannot resolve address of overloaded function
serialize oa(ofs);
^
kabi-serial.cpp:42:3: error: ‘oa’ was not declared in this scope
oa << ql;
And here's the kabi-serial.cpp source ...
#include <boost/serialization/vector.hpp>
#include <vector>
namespace boost {
namespace serialization {
class Cqnodelist
{
public:
friend class boost::serialization::access;
Cqnodelist(){}
std::vector<int>qnodelist;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & qnodelist;
}
};
void kb_write_list ()
{
Cqnodelist ql;
ofstream ofs("kabi-list.dat");
{
serialize oa(ofs);
oa << ql;
}
}
}
}
I based the source code on the simplest of the serialization examples, except using the serialization of the stl vector object.
I'm sure it's simple, but what am I missing?
To use ofstream you need to include <fstream>.
ofstream is in the namespace std: std::ofstream.
You don't need to put your code inside boost::serialization namespace (except case when you implement external to class serialize() function).
Adding serialize method implements way of loading and saving object attributes.
To actually store or load data you need to select storage — archive in Boost.Serialization terminology.
#include <boost/serialization/vector.hpp>
// include headers that implement a archive in simple text format
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <vector>
#include <fstream> // required for std::ofstream
class Cqnodelist
{
public:
friend class boost::serialization::access;
Cqnodelist(){}
std::vector<int>qnodelist;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & qnodelist;
}
};
void kb_write_list ()
{
Cqnodelist ql;
// fill object with data
ql.qnodelist.push_back(1);
ql.qnodelist.push_back(2);
ql.qnodelist.push_back(3);
// See http://www.boost.org/doc/libs/1_57_0/libs/serialization/doc/tutorial.html
// for reference
// save data to archive
{
// open file that will contain serialized data
std::ofstream ofs("kabi-list.dat");
// create archive on top of opened file
boost::archive::text_oarchive oa(ofs);
// write class instance to archive
oa << ql;
}
// to load object later open file, create input archive on top of opened
// file and load object state
{
Cqnodelist new_ql;
// create and open an archive for input
std::ifstream ifs("kabi-list.dat");
boost::archive::text_iarchive ia(ifs);
// read class state from archive
ia >> new_ql;
}
}
int main()
{
kb_write_list();
}

wxWidgets event table with custom event

I'm trying to implement a custom event in my wxWidgets application but I can't write the event table macros in a proper way.
the files that I use to implement the event is like the following:
the .h file
#ifndef __APP_FRAME_H__
#define __APP_FRAME_H__
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <wx/evtloop.h>
#include "wxApp.h"
#include "sampleCefApp.h"
class appFrame: public wxFrame
{
public:
appFrame(const wxString &title, const wxPoint &pos, const wxSize &size);
private:
int OnExit();
void OnCefStartEvent(wxCommandEvent &e);
DECLARE_EVENT_TABLE()
};
#endif
the .cpp file
// File : appFrame.cpp
#include "appFrame.h"
wxDEFINE_EVENT(CEF_START_EVT, wxCommandEvent)
void appFrame::OnCefStartEvent(wxCommandEvent &e)
{
CefRunMessageLoop();
}
int appFrame::OnExit(){
CefShutdown();
Destroy();
return 0;
}
appFrame::appFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
: wxFrame(NULL, wxID_ANY, title, pos, size)
{
}
wxBEGIN_EVENT_TABLE(appFrame, wxFrame)
EVT_COMMAND(wxID_ANY, CEF_START_EVT, appFrame::OnCefStartEvent)
wxEND_EVENT_TABLE()
And when I build my make file I get the following errors:
../src/appFrame.cpp:4:15: error: expected constructor, destructor, or type conversion before ‘(’ token
../src/appFrame.cpp:24:2: error: expected constructor, destructor, or type conversion before ‘wxEventTableEntry
I think the problem is related to mis-placing event table macros.
I want to know what is the problem exactly and how to fix it ?
You need a semicolon after wxDEFINE_EVENT() macro (as for almost all macros with wx prefix, they consistently require a semicolon, unlike the legacy macros without the prefix).
As usual, see the sample for the example of use of this macro.

How to write a C++ API class that will allow a user to register its own callback functions?

Let's say a user links his app against a library I wrote and I want to let him specify a callback function that I will call whenever an error occurs in my library. The implementation below works but I want to double check that I'm not missing something here:
Thread safety
DLL initialization issues
Public API considerations (I'm giving away a reference to an instance from the DLL is that OK?)
Anything that could be done better to hide implementation details from the public API?
errordispatcher.h:
#pragma once
#include <functional>
#include <memory>
#include <string>
namespace WE
{
class ErrorDispatcher
{
public:
ErrorDispatcher()
{}
explicit ErrorDispatcher(std::function<void(std::string)> user_func)
: error_callback_func{user_func}
{}
virtual ~ErrorDispatcher(){}
static ErrorDispatcher& getInstance()
{
return instance_;
}
void setErrorCallback(std::function<void(std::string)> user_func)
{
error_callback_func = nullptr;
if (user_func)
error_callback_func = user_func;
}
void dispatchError(std::string message)
{
if (error_callback_func)
error_callback_func(message);
}
private:
explicit ErrorDispatcher(const ErrorDispatcher&) = delete;
explicit ErrorDispatcher(ErrorDispatcher&&) = delete;
ErrorDispatcher& operator = (const ErrorDispatcher&) = delete;
ErrorDispatcher& operator = (ErrorDispatcher&&) = delete;
static ErrorDispatcher instance_;
std::function<void(std::string)> error_callback_func = nullptr;
};
}
NOTE: above I have inline implementation details in the public header to make this post shorter but they will be moved to a .cpp and won't be part of the public header
errordispatcher.cpp:
#include "errordispatcher.h"
namespace WE
{
ErrorDispatcher ErrorDispatcher::instance_;
}
apitest.h
namespace WE
{
void dllFunctionThatMightGiveError();
}
apitest.cpp
#include "errordispatcher.h"
#include "apitest.h"
namespace WE
{
void dllFunctionThatMightGiveError()
{
// Some error happens in dll so call user function and give a message to the user!
ErrorDispatcher::getInstance().dispatchError("Error in DLL!");
}
}
main.cpp (USER APP)
#include "errordispatcher.h"
#include "apitest.h"
#include <iostream>
#include <string>
void error_callback(std::string message)
{
std::cout << message << "\n";
}
int main(void)
{
WE::ErrorDispatcher::getInstance().setErrorCallback(error_callback);
WE::ErrorDispatcher::getInstance().dispatchError("Error in APP!");
WE::dllFunctionThatMightGiveError();
return 0;
}
Output is:
Error in APP!
Error in DLL!

Boost serialization polymorphic register(export) not working across files

I am using boost::serialization in my project. The project is large, and serializes my objects in several places. According to the documentation here, I should export my class with two separated step.
BOOST_EXPORT_KEY() in .h file, witch contains the declaration.
BOOST_EXPOET_IMPLEMENT() in .cpp file, witch contains the instantiation(definition) of the exporting.
hier.h the class hierarchy, there are 3 classes in the hierarchy.
/*
B <---+--- D1
|
+--- D2
*/
#include <boost/serialization/base_object.hpp>
class B {
public:
virtual ~B() {}
template < typename Ar >
void serialize(Ar& ar, const int) {
}
} ;
class D1 : public B {
public:
virtual ~D1() {}
template < typename Ar > void serialize(Ar& ar, const int) {
boost::serialization::base_object<B>(*this);
}
} ;
class D2 : public B {
public:
template < typename Ar > void serialize(Ar& ar, const int) {
boost::serialization::base_object<B>(*this);
}
virtual ~D2() {}
} ;
#include <boost/serialization/export.hpp>
BOOST_CLASS_EXPORT_KEY(B);
BOOST_CLASS_EXPORT_KEY(D1);
BOOST_CLASS_EXPORT_KEY(D2);
And a hier.cpp contains the implementation:
#include <boost/serialization/export.hpp>
#include "hier.h"
BOOST_CLASS_EXPORT_IMPLEMENT(D1);
BOOST_CLASS_EXPORT_IMPLEMENT(D2);
And a main.cpp use the serialization:
#include <iostream>
#include <sstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
#include "hier.h"
int main(int argc, char* argv[])
{
B* d1 = new D1();
B* d2 = new D2();
std::ostringstream os;
boost::archive::text_oarchive oa (os);
oa & d1 & d2;
}
It compiled without any problem, but run it will cause:
terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): unregistered class - derived class not registered or exported
Which means the derived class is not registered, means the registration in the hier.cpp is not working. But that is really strange, because:
If I register implementation is both main.cpp and hier.cpp, it issue duplicated definition while linking. Means the registration in hier.cpp is OK and is exposed into the linkers visibility., otherwise there will be no duplicated definition error.
If I register implementation only in main.cpp, it runs OK.
I am really confused in that situation. Any comment and suggestion is appreciated. Thanks in advance.
Before calling BOOST_CLASS_EXPORT_* you should include the archives which you want to use. The maсro then adds specific serialize-functions for the headers.
This means you should change your code in hier.cpp to the following:
#include <boost/serialization/export.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include "hier.h"
BOOST_CLASS_EXPORT_IMPLEMENT(D1);
BOOST_CLASS_EXPORT_IMPLEMENT(D2);
The code in hier.h changes accordingly:
#include <boost/serialization/export.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
BOOST_CLASS_EXPORT_KEY(B);
BOOST_CLASS_EXPORT_KEY(D1);
BOOST_CLASS_EXPORT_KEY(D2);
Sources:
Boost Serialization Documentation
PS:
I do not know if this is solving your problem, but I think it could be causing some trouble. I think it's worth a try.

Resources