Skip to content

Instantly share code, notes, and snippets.

@martinmoene
Last active December 15, 2015 11:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martinmoene/5254009 to your computer and use it in GitHub Desktop.
Save martinmoene/5254009 to your computer and use it in GitHub Desktop.
A String class to use over a DLL boundary, enabling the use of different compiler versions at both ends.
//
// Note: use _bstr_t. It's part of COM and present in VC6 and newer versions of Visual C++.
// It's an encapsulation of the BSTR string type that has a shared *C* API. It's used for
// interlanguage operability, so going between compiler/library versions is *not* a problem.
//
// Thanks to the kind people on the accu-general mailing list of http://accu.org/
//
//============================================================================
// String.h
#ifndef G_STRING_H_INCLUDED
#define G_STRING_H_INCLUDED
// define DLL_EXPORTING when generating DLL
#ifdef DLL_EXPORTING
# define DLL_PUBLIC __declspec( dllexport )
#else
# define DLL_PUBLIC __declspec( dllimport )
#endif
#include <string>
class DLL_PUBLIC String
{
public:
~String();
explicit String( char const * const text );
String( String const & other );
String & operator=( String rhs );
String & operator=( char const * const text );
String & swap( String & other );
operator char const *() const
{
return c_str();
}
char const * c_str() const
{
return get();
}
friend String to_String( std::string const & text )
{
return String( text.c_str() );
}
friend std::string to_string( String const & text )
{
return text.c_str();
}
friend char const * to_cstr( String const & text )
{
return text.c_str();
}
private:
const char * get() const;
private:
class Impl;
Impl const * impl;
};
#endif // G_STRING_H_INCLUDED
//============================================================================
// String.cpp
#include "String.h"
class DLL_PUBLIC String::Impl
{
public:
~Impl()
{
delete text;
}
Impl( char const * const text )
: text ( _strdup( text ) )
{
}
Impl * clone() const
{
return new Impl( text );
}
char const * const text;
};
DLL_PUBLIC String::~String()
{
delete impl;
}
DLL_PUBLIC String::String( char const * const text )
: impl( new Impl( text ) )
{
}
DLL_PUBLIC String::String( String const & other )
: impl( other.impl->clone() )
{
}
DLL_PUBLIC String & String::swap( String & other )
{
std::swap( impl, other.impl );
return *this;
}
DLL_PUBLIC String & String::operator=( String rhs )
{
rhs.swap( *this );
return *this;
}
String & String::operator=( char const * const text )
{
return *this = String( text );
}
DLL_PUBLIC const char * String::get() const
{
return impl->text;
}
//============================================================================
// String-test.cpp
// VC2010: cl -nologo -W3 -EHsc -LD -MD -D_CRT_SECURE_NO_WARNINGS -DDLL_EXPORTING String.cpp
// VC6: cl -nologo -W3 -EHsc String-test.cpp String.lib
#include "String.h"
#include <iostream>
std::ostream & operator<<( std::ostream & os, String const & text )
{
return os << text.c_str() ;
}
int main()
{
String text1( "Hello world");
std::cout << text1 << std::endl;
std::cout << ((char const *)text1) << std::endl;
std::cout << to_cstr( text1 ) << std::endl;
String text2( text1 );
std::cout << text2 << std::endl;
String text3( String( "Hi there" ) );
std::cout << text3 << std::endl;
String text4( text2 );
text4 = text3;
std::cout << text4 << std::endl;
text4 = "Ho Ho";
std::cout << text4 << std::endl;
text4 = to_String( std::string( "Hi Hi" ) );
std::cout << text4 << std::endl;
std::string stdtext1( text1 );
std::cout << stdtext1 << std::endl;
std::string stdtext2( to_string( text1 ) );
std::cout << stdtext2 << std::endl;
return 0;
}
//============================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment