6
votes

I recently created a static C++ library in Visual Studio 2008. In this project i used some methods of the std::string class. Now i want to use this library in a Visual Studio 2013 project.

The problem is:
Both Visual Studio versions use different platform toolsets and the project will not compile because of linker errors like:

Error 4 error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string,class std::allocator >::basic_string,class std::allocator >(void)" (__imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ)

Is there any way to make a library compatible with all platform toolsets and using some standard classes like std::string?

FYI: VS2008 is using v90 platform toolset and VS2013 is using v120 platform toolset.

Thanks.

Edit:

If i use some standard methods in the library like std::vector, i can't implement the library anymore.

This works:

unsigned int TestClass::TestMethod()
{   
    return 2;
}

This doesn't:

unsigned int TestClass::TestMethod()
{
    std::vector<unsigned char> vtest;
    vtest.push_back(0xff);

    return 2;
}

Error:

Error 1 error LNK2019: unresolved external symbol "public: static void __cdecl std::_String_base::_Xran(void)" (?_Xran@_String_base@std@@SAXXZ) referenced in function "public: class std::basic_string,class std::allocator > & __thiscall std::basic_string,class std::allocator >::assign(class std::basic_string,class std::allocator > const &,unsigned int,unsigned int)" (?assign@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@ABV12@II@Z)

RT lib is set to /MT and whloe program optimization is disabled (/GL).

Is there any way to fix this?

Thanks.

3
Can you take a look at the runtime library? There might be a mismatch (/MD /MT options)Marco A.
If i change the Runtime Library options to /MTd it works well but only in the debug mode. If i change it to /MT to compile a release i get following error: Error 1 error C1047: The object or library file 'C:\Users\...\TestLib\TestLib.lib' was created with an older compiler than other objects; rebuild old objects and librariesuser4105410
Any chance to have those lib rebuilt with the new compiler?Marco A.
Of course. But is this new generated library compatible with older compilers?user4105410
Sorry I didn't get it: you have an old library and you want to use it in a VS2013 project, right? Can't you recompile that library with VS2013 along with your project and have everything up-to-date?Marco A.

3 Answers

3
votes

As discussed in the comments, you need to make sure that:

  • There's no runtime library mismatch (/MT /MD options) with the older library

  • /GL (i.e. whole program optimization) is disabled

1
votes

While Marco's answer is certainly useful on a technical level, you have a deeper problem with this design:

You cannot use any std library types in the (public) headers of your static library. Not. Any.

While it may work for some it may break for others, and you will find zero documentation or help which ones will work.

std:: types are not (guaranteed to be) binary compatible between different platform toolset versions, so using any in any interface or as a class member will break sooner or later.

By example:

  1. This is OK, use of vector is purely internal:

    unsigned int TestClass::TestMethod()
    {
        std::vector<unsigned char> vtest;
        vtest.push_back(0xff);
    
        return 2;
    }
    
  2. This will break, at runtime, if the two platform toolset compilers+options produce a different binary layout for vector objects:

    unsigned int TestClass::Test2(std::vector<unsigned char> const& vparam)
    {
        vparam.push_back(0xff);
    
        return 2;
    }
    
  3. This will also break for different binary layout:

    class TestClass {
      std::vector<int> m_buffer;
      ...
    };
    

And the problem with a static library, as opposed to a DLL, is of course that it is a lot less obvious what goes into the interface and what not (because there's no need to dllexport or anything.)

Do note however, that the technical problem per se is absolutely the same for the DLL as for the static LIB. I.e., you can not use any std types in the interface of your DLL/LIB, that includes, at least:

  • class members (even private ones)
  • function parameters (regardless of whether you pass by-value, by-ref or by-pointer)
  • function return values
0
votes

Problem solved:

I created a dll instead of a static library.

Also make sure that program optimization (/GL) is disabled and check the /MT /MD options.

To create a dll i set the configuration type of the library to "Dynamic Linked Library (.dll)" and defined __declspec(dllexport) in the header files like:

#define TEST_EXPORT
#ifdef TEST_EXPORT
#define TEST __declspec(dllexport) 
#else
#define TEST __declspec(dllimport) 
#endif


class TestClass
{
public:
    std::string TEST TestMethod(); 
};