I am getting those weird linker errors (using the Free Toolkit
2003), they do not appear using VS2005:
Linking CXX executable ..\..\..\..\bin\gdcmCommonTests.exe
gdcmCommon.lib(gdcmCommon.dll) : error LNK2005: "public: int
__thiscall std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::compare(char const *)const " (?compare@?
$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEHPBD@Z)
already defined in TestFilename.obj
gdcmCommon.lib(gdcmCommon.dll) : error LNK2005: "public: class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > & __thiscall std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >::operator
+=(char)" (??Y?$basic_string@DU?$char_traits@D@std@@V?
$allocator@D@2@@std@@QAEAAV01@D@Z) already defined in TestFilename.obj
gdcmCommon.lib(gdcmCommon.dll) : error LNK2005: "public: unsigned int
__thiscall std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::max_size(void)const " (?max_size@?
$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIXZ)
already defined in TestDirectory.obj
gdcmCommon.lib(gdcmCommon.dll) : error LNK2005: "public: class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > & __thiscall std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >::erase(unsigned
int,unsigned int)" (?erase@?$basic_string@DU?$char_traits@D@std@@V?
$allocator@D@2@@std@@QAEAAV12@II@Z) already defined in
TestByteSwap.obj
TestString.obj : error LNK2019: 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)
referenced in function "class std::basic_istream<char,struct
std::char_traits<char> > & __cdecl std::getline<char,struct
std::char_traits<char>,class std::allocator<char> >(class
std::basic_istream<char,struct std::char_traits<char> > &,class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > &,char)" (??$getline@DU?$char_traits@D@std@@V?
$allocator@D@2@@std@@YAAAV?$basic_istream@DU?
$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?
$char_traits@D@std@@V?$allocator@D@2@@0@D@Z)
..\..\..\..\bin\gdcmCommonTests.exe : fatal error LNK1120: 1
unresolved externals
Thanks for suggestion
-Mathieu
It seems that you're mixing static and dynamic runtime libraries.
Ensure that all parts of your project use the same flavor of
runtime libraries.
Alex
Here is the set of flags I am using:
"/DWIN32 /D_WINDOWS /W3 /Zm1000 /GX /GR /MT /O2 /Ob2 /D NDEBUG"
I cannot use /MD since the free Toolkit 2003 does not have a
MSVCRT.lib.
Does this still looks right ?
Thanks
-Mathieu
Just for reference my compiler flag are perfectly fine, and I was
using all the correct libraries. But there is one thing you cannot do
in MSC compiler:
#if defined(WIN32)
#if (defined(gdcmCommon_EXPORTS)
#define GDCM_EXPORT __declspec( dllexport )
#else
#define GDCM_EXPORT __declspec( dllimport )
#endif
#else
#define GDCM_EXPORT
#endif
class GDCM_EXPORT String : public std::string { ... }
Could someone please let a poor UNIX guy understand what is the issue
here (I have very little knowledge on ho dll actually works) ?
Thanks
-Mathieu
There is nothing wrong with the command line. However, you need to
ensure that all files in your project are compiled with the same
CRT settings. Also, any external LIB that you link with must use
the same CRT.
In your project gdcmCommonTests.exe is linked with gdcmCommon.lib
(which is actually import library for gdcmCommon.dll) and both of
them try to share `std::basic_string' instances. It can be done
only if both EXE and DLL link dynamically with CRT. You have two
options:
1. Link everything dynamically with CRT.
2. Don't share CRT/Standard C++ objects between modules.
Alex
You said that Toolkit 2003 does not support dynamic linking. If it
is so, then you cannot share standard containers between modules.
It happens because each module has its own instance of CRT, which
tracks allocations. Hope this helps:
"How to export an instantiation of a Standard Template Library
(STL) class and a class that contains a data member that is an STL
object"
http://support.microsoft.com/kb/168958
Alex
Wait: just for the record, you are _NOT_ mixing output of different C++
compilers, right? If you want to use C++ interfaces (e.g. from a DLL), they
must be compiled with the same compiler.
> Just for reference my compiler flag are perfectly fine, and I was
> using all the correct libraries. But there is one thing you cannot
> do in MSC compiler:
>
> #if defined(WIN32)
> #if (defined(gdcmCommon_EXPORTS)
> #define GDCM_EXPORT __declspec( dllexport )
> #else
> #define GDCM_EXPORT __declspec( dllimport )
> #endif
> #else
> #define GDCM_EXPORT
> #endif
>
> class GDCM_EXPORT String : public std::string { ... }
I see one problem here: std::string is not intended as baseclass, so the
library in question already uses questionable constructs. If you want to
implement a type in terms of std::string you should wrap is as a member (or
at most a private baseclass), otherwise it can well be extended using plain
functions, just like the STL doesn't force every algorithm into the
containers but keeps them externally, too.
Anyway, neither of this is really your problem. The problem is rather that
this code will also implicitly export parts of std::string from that DLL. I
personally consider that a bug in the compiler. Now, what happens is that
in one translation unit you include <gcdm/string.h>, which tells the
compiler it can import std::string functions from the DLL, while in another
translation unit you only include <string> which generates those functions
inline. At link time, those definitions then cause
error LNK2005: "public: int std::string::compare(char const *) const"
already defined in TestFilename.obj
Now, the simple workaround is to include <gcdm/string.h> in both translation
units.
> Could someone please let a poor UNIX guy understand what is the issue
> here (I have very little knowledge on ho dll actually works) ?
Basically DLLs are like Unix shared objects, only that you have to
explicitly say which parts are exported via __declspec(dllexport). Your
issues have nothing to do with the differences between SOs and DLLs though,
they are rather a compiler bug.
Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite
Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932
Hum, I'll have to rethink that, but I needed a quick implementation of
a std::string, where I could overload the function
inline std::istream& operator>>(std::istream &is, String &ms);
Making it a member means a lot more duplication of code AFAIK (but
I'll double check that).
> Anyway, neither of this is really your problem. The problem is rather that
> this code will also implicitly export parts of std::string from that DLL. I
> personally consider that a bug in the compiler. Now, what happens is that
> in one translation unit you include <gcdm/string.h>, which tells the
> compiler it can import std::string functions from the DLL, while in another
> translation unit you only include <string> which generates those functions
> inline. At link time, those definitions then cause
>
> error LNK2005: "public: int std::string::compare(char const *) const"
> already defined in TestFilename.obj
Makes perfect sense !
> Now, the simple workaround is to include <gcdm/string.h> in both translation
> units.
sweet :)
> > Could someone please let a poor UNIX guy understand what is the issue
> > here (I have very little knowledge on ho dll actually works) ?
>
> Basically DLLs are like Unix shared objects, only that you have to
> explicitly say which parts are exported via __declspec(dllexport). Your
> issues have nothing to do with the differences between SOs and DLLs though,
> they are rather a compiler bug.
Thanks a lot for all those details, the bug is a lot less cryptic
now :)
-Mathieu