Konstantin
Konstantin

Reputation: 115

Problem passing std::string though DLL boundaries with visual studio

I have a DLL that contains some code like this:

class Info {
    int a
    int b
    int c
    std::string str1;
    std::string str2;
};

__declspec(dllexport) class C {
    Info getInfo();
}

I compile this code with Visual Studio 2015, and calling C::getInfo() works perfectly fine on my system.

Now somebody else is trying to use the DLL, and he's also using Visual Studo 2015. The call goes well but the strings don't contain any accessible data. Even the debugger reports "Error reading characters of string", and the program crashes when trying to read it.

There was also a similar problem with std::vector which I could solve by inlining the code that created the vector.

To me this looks like either the other person is using a different STL version, or the compiler somehow produces a different memory layout for std::string (though he claims to use default settings).

Is this possible? I saw there are different updates for VS 2015 and we might not have the same updates installed.

Any recommendations for fixing this? I can't move to char* without significantly breaking the API. Most users don't even use Visual Studio (or Windows), so this hasn't been a problem until now.

Upvotes: 1

Views: 1860

Answers (1)

Bathsheba
Bathsheba

Reputation: 234785

That's life I'm afraid. Unless you have exactly the same compiler (including C++ Standard Library) and compiler settings, this is not guaranteed to work. I'm not convinced from a C++ Standards perspective that even this is guaranteed to work. It's pretty nigh on impossible to build an ABI in C++. In your specific example, there's no guarantee that the struct will be built with the same alignment characteristics. sizeof(std::string) varies considerably due in part to short string optimisations which can even be compiler-configurable.

Alternatives:

  1. Use C linkage for your exported functions and char*-style interfaces that are allocated and deallocated by the caller (cf. the Windows API). (Don't ever allocate memory in the client and deallocate in the dll, and vice-versa.)

  2. Make sure the user of your library can build it from the source files. Consider distributing as a static library rather than a dynamic one, as the former are a little easier to work with.

Upvotes: 1

Related Questions