fix linking problems due to MSVC implicitly considering template classes specializations used as base classes DLL-exported even though it doesn't actually export them when building the DLL (with or without explicit declspec(dllexport)); also replace wxCharTypeBuffer::NullData with a static function to allow not DLL-exporting this class

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-10-30 23:04:29 +00:00
parent 10d256d6c8
commit 6b583d40a8
4 changed files with 55 additions and 85 deletions

View File

@@ -27,7 +27,7 @@ class WXDLLIMPEXP_FWD_BASE wxCStrData;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
template <typename T> template <typename T>
class WXDLLIMPEXP_BASE wxCharTypeBuffer class wxCharTypeBuffer
{ {
public: public:
typedef T CharType; typedef T CharType;
@@ -37,7 +37,7 @@ public:
if ( str ) if ( str )
m_data = new Data(wxStrdup(str)); m_data = new Data(wxStrdup(str));
else else
m_data = &NullData; m_data = GetNullData();
} }
wxCharTypeBuffer(size_t len) wxCharTypeBuffer(size_t len)
@@ -64,7 +64,7 @@ public:
// that ref-counting is used, it's not really needed. // that ref-counting is used, it's not really needed.
CharType *release() const CharType *release() const
{ {
if ( m_data == &NullData ) if ( m_data == GetNullData() )
return NULL; return NULL;
wxASSERT_MSG( m_data->m_owned, _T("can't release non-owned buffer") ); wxASSERT_MSG( m_data->m_owned, _T("can't release non-owned buffer") );
@@ -121,7 +121,7 @@ public:
if ( !str ) if ( !str )
return false; return false;
if ( m_data == &NullData ) if ( m_data == GetNullData() )
{ {
m_data = new Data(str); m_data = new Data(str);
} }
@@ -167,30 +167,27 @@ private:
}; };
// placeholder for NULL string, to simplify this code // placeholder for NULL string, to simplify this code
// NB: this is defined in string.cpp, not (non-existent) buffer.cpp static Data *GetNullData()
#ifdef __MINGW32__ {
// MinGW requires explicit WXDLLIMPEXP_DATA_BASE to avoid compilation static Data s_nullData(NULL);
// errors
static WXDLLIMPEXP_DATA_BASE(Data) NullData; return &s_nullData;
#else }
// but Visual C++ doesn't like it
static Data NullData;
#endif
void IncRef() void IncRef()
{ {
if ( m_data == &NullData ) // exception, not ref-counted if ( m_data == GetNullData() ) // exception, not ref-counted
return; return;
m_data->m_ref++; m_data->m_ref++;
} }
void DecRef() void DecRef()
{ {
if ( m_data == &NullData ) // exception, not ref-counted if ( m_data == GetNullData() ) // exception, not ref-counted
return; return;
if ( --m_data->m_ref == 0 ) if ( --m_data->m_ref == 0 )
delete m_data; delete m_data;
m_data = &NullData; m_data = GetNullData();
} }
private: private:
@@ -199,7 +196,7 @@ private:
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> ) WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
class WXDLLIMPEXP_BASE wxCharBuffer : public wxCharTypeBuffer<char> class wxCharBuffer : public wxCharTypeBuffer<char>
{ {
public: public:
typedef wxCharTypeBuffer<char> wxCharTypeBufferBase; typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
@@ -216,7 +213,7 @@ public:
#if wxUSE_WCHAR_T #if wxUSE_WCHAR_T
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> ) WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
class WXDLLIMPEXP_BASE wxWCharBuffer : public wxCharTypeBuffer<wchar_t> class wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
{ {
public: public:
typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase; typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
@@ -342,7 +339,7 @@ private:
}; };
class WXDLLIMPEXP_BASE wxMemoryBuffer class wxMemoryBuffer
{ {
public: public:
// ctor and dtor // ctor and dtor

View File

@@ -3605,7 +3605,7 @@ private:
#endif // !wxUSE_STL_BASED_WXSTRING #endif // !wxUSE_STL_BASED_WXSTRING
template<typename T> template<typename T>
class WXDLLIMPEXP_BASE wxStringTypeBufferBase class wxStringTypeBufferBase
{ {
public: public:
typedef T CharType; typedef T CharType;
@@ -3645,8 +3645,7 @@ protected:
}; };
template<typename T> template<typename T>
class WXDLLIMPEXP_BASE wxStringTypeBufferLengthBase class wxStringTypeBufferLengthBase : public wxStringTypeBufferBase<T>
: public wxStringTypeBufferBase<T>
{ {
public: public:
wxStringTypeBufferLengthBase(wxString& str, size_t lenWanted = 1024) wxStringTypeBufferLengthBase(wxString& str, size_t lenWanted = 1024)
@@ -3750,25 +3749,57 @@ typedef wxStringInternalBufferLength wxUTF8StringBufferLength;
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferBase<char> ) WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferBase<char> )
class WXDLLIMPEXP_BASE wxUTF8StringBuffer : public wxStringTypeBufferBase<char> // Note about inlined dtors in the classes below: this is done not for
// performance reasons but just to avoid linking errors in the MSVC DLL build
// under Windows: if a class has non-inline methods it must be declared as
// being DLL-exported but, due to an extremely interesting feature of MSVC 7
// and later, any template class which is used as a base of a DLL-exported
// class is implicitly made DLL-exported too, as explained at the bottom of
// http://msdn.microsoft.com/en-us/library/twa2aw10.aspx (just to confirm: yes,
// _inheriting_ from a class can change whether it is being exported from DLL)
//
// But this results in link errors because the base template class is not DLL-
// exported, whether it is declared with WXDLLIMPEXP_BASE or not, because it
// does have only inline functions. So the simplest fix is to just make all the
// functions of these classes inline too.
class wxUTF8StringBuffer : public wxStringTypeBufferBase<char>
{ {
public: public:
wxUTF8StringBuffer(wxString& str, size_t lenWanted = 1024) wxUTF8StringBuffer(wxString& str, size_t lenWanted = 1024)
: wxStringTypeBufferBase<char>(str, lenWanted) {} : wxStringTypeBufferBase<char>(str, lenWanted) {}
~wxUTF8StringBuffer(); ~wxUTF8StringBuffer()
{
wxMBConvStrictUTF8 conv;
size_t wlen = conv.ToWChar(NULL, 0, m_buf);
wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
wxStringInternalBuffer wbuf(m_str, wlen);
conv.ToWChar(wbuf, wlen, m_buf);
}
DECLARE_NO_COPY_CLASS(wxUTF8StringBuffer) DECLARE_NO_COPY_CLASS(wxUTF8StringBuffer)
}; };
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferLengthBase<char> ) WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferLengthBase<char> )
class WXDLLIMPEXP_BASE wxUTF8StringBufferLength class wxUTF8StringBufferLength : public wxStringTypeBufferLengthBase<char>
: public wxStringTypeBufferLengthBase<char>
{ {
public: public:
wxUTF8StringBufferLength(wxString& str, size_t lenWanted = 1024) wxUTF8StringBufferLength(wxString& str, size_t lenWanted = 1024)
: wxStringTypeBufferLengthBase<char>(str, lenWanted) {} : wxStringTypeBufferLengthBase<char>(str, lenWanted) {}
~wxUTF8StringBufferLength(); ~wxUTF8StringBufferLength()
{
wxCHECK_RET(m_lenSet, "length not set");
wxMBConvStrictUTF8 conv;
size_t wlen = conv.ToWChar(NULL, 0, m_buf, m_len);
wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
wxStringInternalBufferLength wbuf(m_str, wlen);
conv.ToWChar(wbuf, wlen, m_buf, m_len);
wbuf.SetLength(wlen);
}
DECLARE_NO_COPY_CLASS(wxUTF8StringBufferLength) DECLARE_NO_COPY_CLASS(wxUTF8StringBufferLength)
}; };

View File

@@ -2096,48 +2096,3 @@ int wxString::Freq(wxUniChar ch) const
} }
return count; return count;
} }
// ----------------------------------------------------------------------------
// wxUTF8StringBuffer
// ----------------------------------------------------------------------------
#if wxUSE_UNICODE_WCHAR
wxUTF8StringBuffer::~wxUTF8StringBuffer()
{
wxMBConvStrictUTF8 conv;
size_t wlen = conv.ToWChar(NULL, 0, m_buf);
wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
wxStringInternalBuffer wbuf(m_str, wlen);
conv.ToWChar(wbuf, wlen, m_buf);
}
wxUTF8StringBufferLength::~wxUTF8StringBufferLength()
{
wxCHECK_RET(m_lenSet, "length not set");
wxMBConvStrictUTF8 conv;
size_t wlen = conv.ToWChar(NULL, 0, m_buf, m_len);
wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
wxStringInternalBufferLength wbuf(m_str, wlen);
conv.ToWChar(wbuf, wlen, m_buf, m_len);
wbuf.SetLength(wlen);
}
#endif // wxUSE_UNICODE_WCHAR
// ----------------------------------------------------------------------------
// wxCharBufferType<T>
// ----------------------------------------------------------------------------
#ifndef __VMS_BROKEN_TEMPLATES
template<>
#endif
wxCharTypeBuffer<char>::Data
wxCharTypeBuffer<char>::NullData(NULL);
#ifndef __VMS_BROKEN_TEMPLATES
template<>
#endif
wxCharTypeBuffer<wchar_t>::Data
wxCharTypeBuffer<wchar_t>::NullData(NULL);

View File

@@ -542,16 +542,3 @@ wxU16CharBuffer wxUString::utf16_str() const
return result; return result;
} }
#if SIZEOF_WCHAR_T != 2
template<>
wxCharTypeBuffer<wxChar16>::Data
wxCharTypeBuffer<wxChar16>::NullData(NULL);
#endif
#if SIZEOF_WCHAR_T != 4
template<>
wxCharTypeBuffer<wxChar32>::Data
wxCharTypeBuffer<wxChar32>::NullData(NULL);
#endif