A lot of years ago i made the mistake to inherit from std::string in DLL and put some funktions like "MakeUpper" to the string. Converting from VS2008 to VS2012 the problem whith the npos pops up. With a workaround from microsoft * i get some other DLLs working, but not DLLs which are used late-binding and have no DLLMain() function.
*Microsoft Workaround
#if _MSC_VER >= 1600
#include <string>
const std::basic_string<char>::size_type std::basic_string<char>::npos = (std::basic_string<char>::size_type) -1;
#endif
The class is declared in a DLL like this:
class MYDLL_API CNyString : public std::string
the errorline is this:
error LNK2001: unresolved external symbol "public: static unsigned int const std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::npos" (?npos#?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##2IB)
Rewriting the MyString class with an std::string as attribute does not work because it is used in several other DLLs where MyString and string functions are mixed a lot, also in function parameters. Example:
void Foo(const CMyString &Param_) ..
...
Foo(std::string("Hallo World")..
Does anyone has an idea how to solve this problem ?
Thanks in advance.
Related
I normally work in c# and am out of my wits for this one . I used Walkthrough: Creating and Using a Dynamic Link Library (C++) to create a Dynamic Link Library.
I have defined two methods as shown below
DeveloperConsoleManager.h
#pragma once
#include "atlstr.h"
#ifdef DEVCONSOLEMANAGER_EXPORTS
#define DEVCONSOLEMANAGER_API __declspec(dllexport)
#else
#define DEVCONSOLEMANAGER_API __declspec(dllimport)
#endif
namespace DeveloperConsoleManager
{
class DeveloperConsoleLogic
{
public:
// Returns a + b
static DEVCONSOLEMANAGER_API double Add(double a, double b);
static DEVCONSOLEMANAGER_API bool CheckforValidFile(CString fileName);
};
}
DeveloperConsoleManager.cpp
// DeveloperConsoleManager.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "DeveloperConsoleManager.h"
namespace DeveloperConsoleManager
{
double DeveloperConsoleLogic::Add(double a, double b)
{
return a + b;
}
bool DeveloperConsoleLogic :: CheckforValidFile(CString fileName)
{
return false;
}
}
I use these methods in a .cpp file in a different project (type: Application (.exe)). When I Build the solution, there are following linker errors
Warning 1 warning C4273: 'DeveloperConsoleManager::DeveloperConsoleLogic::Add' : inconsistent dll linkage e:\md_69\developerconsolemanager\developerconsolemanager.cpp 10
Warning 2 warning C4273: 'DeveloperConsoleManager::DeveloperConsoleLogic::CheckforValidFile' : inconsistent dll linkage e:\md_69\developerconsolemanager\developerconsolemanager.cpp 16
Error 3 error LNK2028: unresolved token (0A0004F1) "public: static bool __cdecl DeveloperConsoleManager::DeveloperConsoleLogic::CheckforValidFile(class ATL::CStringT > >)" (?CheckforValidFile#DeveloperConsoleLogic#DeveloperConsoleManager##$$FSA_NV?$CStringT#_WV?$StrTraitMFC_DLL#_WV?$ChTraitsCRT#_W#ATL#####ATL###Z) referenced in function "public: void __thiscall CSaSsiConsoleUi::UploadSsiCheck(void)" (?UploadSsiCheck#CSaSsiConsoleUi##$$FQAEXXZ) E:\MD_69\DeveloperConsoleUI\SaSsiConsoleUI.obj
Error 4 error LNK2019: unresolved external symbol "public: static bool __cdecl DeveloperConsoleManager::DeveloperConsoleLogic::CheckforValidFile(class ATL::CStringT > >)" (?CheckforValidFile#DeveloperConsoleLogic#DeveloperConsoleManager##$$FSA_NV?$CStringT#_WV?$StrTraitMFC_DLL#_WV?$ChTraitsCRT#_W#ATL#####ATL###Z) referenced in function "public: void __thiscall CSaSsiConsoleUi::UploadSsiCheck(void)" (?UploadSsiCheck#CSaSsiConsoleUi##$$FQAEXXZ) E:\MD_69\DeveloperConsoleUI\SaSsiConsoleUI.obj
Error 5 error LNK1120: 2 unresolved externals E:\MD_69\Debug\DeveloperConsoleUi.exe
There is no linker error for the "Add" method.
I have already included "DeveloperConsoleManager.lib" in Linker -> Input -> Additional Dependencies. Please help me find out what exactly am I doing wrong.
I would be glad to add any additional information needed.
Thanks to #Igor Tandetnik and the awesome thing that is internet, I figured it out. I am adding it as an answer so that some one else might benefit.
The problem was with CString. The project in which the function was defined was a dynamic link library (dll) and the call was being made from an MFC application. Now, the issue was that, MFC uses for CString while the non-MFC dll uses .
CString in is defined as:
typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;
while in is defined as:
typedef CStringT< TCHAR, StrTraitATL< TCHAR > > CString;
This, as you can clearly see is different. The workaround I used was using CAtlString instead of CString . However, please feel free to suggest any better way if you come across.
for various reasons I subclassed the std::string like:
class CotengString : public string
{
public:
// Constructors
CotengString();
CotengString(const char* ch) : string(ch) {}
CotengString(const string& str) : string(str) {}
virtual ~CotengString() {};
//Operator"="
CotengString& operator=(const string& str) { return (CotengString&)this->assign(str); }
CotengString& operator=(const char* ch) { return (CotengString&)this->assign(ch); }
};
Inside the DLL I wish to use this code all compiles correctly. But inside my Google Test project I get this error after switching to the subclassed string
LNK2005 "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *,unsigned int)" (??0?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##QAE#PBDI#Z) already defined in gtest.lib(gtest-all.obj) Devices.Spectro.CppTest <path>\Devices.Spectro.CppTest\Devices.Spectro.Cpp.lib(Devices.Spectro.Cpp.dll)
My gut feeling is that I am missing something obvious. But I don't know what it could be
Okay, then as answer.
First cause
This seems to me to be a problem of multiple includes of header files.
This results in that the compiler wants to compile functions or in this case allocators again and detects "oh I already compiled that!".
So fix would be to add to the header file this:
#ifndef CUSTOM_STRING_IMPLEMENTATION_HEADER
#define CUSTOM_STRING_IMPLEMENTATION_HEADER
....
#endif
Second cause
However, if this isn't the case maybe you're trying to compile this file again in your code which uses the dll which already contains the compiled class.
I personally think it's the second cause according to your log file. There's said that the allocator is already compiled in your library.
Example:
If you're using only header files this results in a big problem. Look here.
Dll code:
SomeHeaderFile.hpp
class NiceClass{
//Constructor is implemented. That causes several problems now!
NiceClass{
}
...
}
Your application code (wich uses the dll):
SomeNiceApplicationCode:
//Linker error now! It's already compiled right into your dll!
#include <SomeHeaderFile.hpp>
int main(){
NiceClass niceClassInstance;
return 0;
}
Solution:
Apply those changes and create and extra cpp file for your class.
Include in your application file only the header file.
class CotengString : public string
{
public:
// Constructors
CotengString();
CotengString(const char* ch) : string(ch); //Use cpp file!
CotengString(const string& str) : string(str); //""
virtual ~CotengString(); //""
//Operator"="
CotengString& operator=(const string& str); //Same for this
CotengString& operator=(const char* ch); //""
};
These type of errors are well discussed on SO and many other places, yet, I couldnt find a solution to my particular case.
Basically, I have made a static library project in my solution to seperate some functionality, and reference it in my current project. When I try to call a function from the library, i got this notorious linker error. I think there are no problems in setting up the project (references, dependencies etc.) .
First, I will give some minimal example of what I am working on ( there are some third party classes )
//FileReader.h
class IBKFileReader{
public:
virtual ~IBKFileReader() {} ;
virtual void readFile(std::string fileName, pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud ) = 0 ;
};
class XYZFileReader : public IBKFileReader
{
public:
virtual void readFile(std::string fileName, pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud )
{
}
And in my code, I call readFile function on a IBKFileReader object polymorphically.
And, this part is ok, without any errors, it compiles, links and runs.
However, when I move the body of the readFile function to a .cpp file and implement it there
(with the same signature hopefully, i copy pasted) , I got the unresolved external symbol error. This is the header of the function in .cpp file.
void XYZFileReader::readFile(std::string fileName, pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud )
It seems that implementing the function body inline in the header file, and implementing in some seperate file makes a difference.
What do you think of this issue? Has anybody experienced something similar to this? I hope I am not missing out something obvious.
EDIT:
This is the error log i get:
1>main.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl XYZFileReader::readFile(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class boost::shared_ptr<class pcl::PointCloud<struct pcl::PointXYZ> >)" (?readFile#XYZFileReader##UEAAXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V?$shared_ptr#V?$PointCloud#UPointXYZ#pcl###pcl###boost###Z)
EDIT:
I may have caused some misunderstanding.
FileReader.h and FileReader.cpp is in static library project. I didnt do more than just implementing the function in the cpp file, definitions and such are still there.
In the same solution, in another project I reference to this project.
I am not getting the linker error when compiling the static lib, but when I am using it.
Sorry for my bad English.
A member function that is defined inside its class member list is called an inline member function. Try moving the member definition out of the class definition.
class XYZFileReader : public IBKFileReader
{
public:
virtual void readFile(std::string fileName,
pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud);
};
void XYZFileReader::readFile(std::string fileName,
pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud) {}
I was getting the following error from Visual Studio:
error LNK2019: unresolved external symbol "public: __thiscall BSTree::BSTreeNode::BSTreeNode(class TestData const &,class BSTree::BSTreeNode *,class BSTree::BSTreeNode *)" (??0BSTreeNode#?$BSTree#VTestData##H##QAE#ABVTestData##PAV01#1#Z) referenced in function "protected: void __thiscall BSTree::insertHelper(class TestData const &,class BSTree::BSTreeNode * &)" (?insertHelper#?$BSTree#VTestData##H##IAEXABVTestData##AAPAVBSTreeNode#1##Z)
Here are the functions that the compiler brings into question:
template < typename DataType, class KeyType >
BSTree<DataType,KeyType>::BSTreeNode::BSTreeNode ( const DataType &nodeDataItem,
BSTreeNode *leftPtr, BSTreeNode *rightPtr ) {
left = leftPtr;
right = rightPtr;
dataItem = nodeDataItem;
}
template < typename DataType, class KeyType >
void BSTree<DataType,KeyType>::insertHelper (const DataType& d, BSTreeNode*& b) {
if (b == 0) {
b = new BSTreeNode(d, 0, 0);
}
else if (d.getKey() < b->dataItem.getKey()) {
insertHelper(d, b->left);
}
else if (d.getKey() > b->dataItem.getKey()) {
insertHelper(d, b->right);
}
else {
b->dataItem = d;
}
}
So I look them over and I believe my code looks correct. So I perform a rebuild and then there are no errors and the program fires up just fine. I asked my lab instructor about why this occurs, but he said that he did not have a suitable answer. This is something that I've seen more and more while my projects are becoming more complex.
I've done some research:
Difference between build, rebuild, and clean solution
Do I always need to Clean/Rebuild?
Is this something that just inevitably happens while working with the Visual Studio IDE? Is there anything that I can do to prevent this? Are there any consequences from having this issue come up (ie. is there a flaw in my code)?
UPDATED: It seems that this might be the cause for much of the linker errors that I've been witnessing the semester.
Here is the advice from a book:
"Compiling programs that use templated classes requires a change in what files are included using the #include preprocessor directive, and in how the program is compiled. Because of how C++ compilers process templated code, the program that creates objects of the classes (e.g., main.cpp) must include the class implementation file, not the class declaration file. That is, it must do #include "Classname.cpp" instead of the usual #include "Classname.h" The rule is in effect the rest of this book. Because the main implementation file does a #include of the class implementation code, the class implementation code is not compiled separately."
I just reorganized some libraries of my Visual C++ (7.1) project and got trouble with the linker i cannot resolve.
The Project links MFC as well as Standard Windows Libraries, all MBCS
Somewhere, there is something like :
std::stringstream sstr;
sstr << m_MyCStringVar << std::endl;
(this line, as well as some others, needs << for basic_stream and CString)
Everything was fine until i merged 2 other libraries into 1 libraries (just moving the code/files from a to b without changing much)
Suddenly, all my exe's produce the linker error:
BasicFunctionsD.lib(CAccess.obj) : error LNK2019: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,class ATL::CStringT > > const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$CStringT#DV?$StrTraitMFC_DLL#DV?$ChTraitsCRT#D#ATL#####ATL###Z) referenced in function "protected: void __thiscall CAccessor::CreateCategory(int,char const *,char const *)" (?CreateCategory#CAccessor##IAEXHPBD0#Z)
(above code wasn't affected from the library merge, at least not directly)
As far as i can recognize, the << operator for basic ostream and CString is not found.
Maybe the lib containing MFC versions of basic_ostream is not found?
But i have no idea how to fix it or even where to start searching for the real problem.
Any hints would be nice
arg...
Simple reason: there is no std::ostream operator with CString... it was my own code and i just did not remember... :(
During cleanup , the function went into a namespace and got lost
D'oh!
namesspace StupidcleanupIshouldNotHavedone
{
std::ostream & operator<<(std::ostream & s, const CString & str)
{
s << (LPCTSTR)str;
return s;
}
}
I'm probably wrong but IIRC i did experience a problem with unresolved links. The solution was get ready...... #include <string>. Turns out one of the headers defined string and i was able to use string normally and compile with no problem. However there was no static implementation since i forgot the header so maybe your missing one.