Ajay, that is indeed an interesting point about not returning STL objects. What did you exactly mean when you said STL doesn't have DLL, no runtime library etc ?
Is it safe to return std::string from DLL functions.
Printable View
[Regarding what I meant with regard to interfaces]
Imagine that I had an interface class as follows :
I could implement it by extending to implement the following classes :Code:class IDisplay
{
virtual void Display(char * _p) = 0;
}
Both the above class implementations would be in the DLL.Code:class ConsoleDisplay : public IDisplay
{
virtual void Display(char *_p)
{
}
}
class FileDisplay : public IDisplay
{
virtual void Display(char *_p)
{
}
}
Now, there could be a function being exposed out of the DLL as follows :
__declspec(dllexport) IDisplay * GetDisplayInstance()
The implementation of GetDisplayInstance() would be to instantiate either FileDisplay or ConsoleDisplay based on some condition.
I had asked the earlier question keeping this scenario in mind with regard to returning object pointers in the guise of interface pointers.
I would like to understand if Igor would make any changes to the way the IDisplay interface is declared (like typing in the _stdcall convention in the signature) and why ?
Ajay, everyone, your comments are also requested - it is good learning indeed.
Somehow I was under the impression that it was best to deal with Basic Data Types when using DLL function signatures, but it seems it is perfectly OK to deal with classes as return types or parameters (except for the cases that Ajay and the others have pointed out)
It isn't practical, as there are too many pitfalls involved.
What if the DLL was created with one version of the compiler, and the app is using another version of the compiler? What if the std::string internals for each version is different?
In addition, let's assume that the DLL and app are built with the same compiler and version. What if the DLL is compiled with one set of options and the app is compiled with a different set of options, making std::string slightly different between the two versions?
OK, let's assume you are compiling with the same options. What if the DLL is using one heap to allocate memory, and the app uses a separate heap for memory allocations. What if the std::string allocates memory in the DLL to do it's internal housekeeping, and then the app takes this string and the std::string on the app side attempts to free or reallocate memory? That isn't going to work, since the heaps are different, and one heap knows nothing about what the other heap is doing or has done. That's a crash waiting to happen.
So all of these things need to be consistent -- same compiler, same version of the compiler, same compiler options, same heap. All of these have to be in sync for any passing of std::string from DLL to app to work successfully.
Regards,
Paul McKenzie
Back to original problem :)
__declspec(dllexport) IDisplay * GetDisplayInstance();
__declspec(dllexport) ReleaseDisplayInstance(IDisplay*);
Looks OK for me.
Is it safe to return std::string from DLL functions?
Never use STL types in Dll interface.
STL doesn't have DLL, no runtime library etc.
Like all template libraries, STL is completely inline. This is not Dll, just a lot of h-files.
Thanks Alex for clarifying regarding how STL is. Somehow I was tending to think it is a DLL.
Would you actually consider std::string to be part of the STL - because there is nothing "template" about that right ? Shouldn't the implementation of std::string be a DLL or something ?
Wrong. A std::string is just a typedef for a template based on the char data type.
or something similar to that.Code:typedef basic_string<char, char_traits<char> > string;
However, just because something is a template doesn't mean it has anything to do with STL. There are standard classes that are based on templates that are not part of STL. The stream classes are a good example of this.
Regards,
Paul McKenzie
You may return const char* for constant strings. For dynamic strings, make function prototype like:
size_t GetString(char* buffer, size_t bufferSize);
Function fills buffer which has at least bufferSize length (caller's responsibility), and returns number of characters actually filled.