Thanks,
EricW
class __declspec( dllexport ) Test
{
public:
CStringWEx m_strName;
};
CStringWEx is a class I derived from the base CString classes.
ServerEngine.lib(ServerEngine.dll) : error LNK2005: "public: __thiscall
ATL::CStringT<wchar_t,class ATL::StrTraitATL<wchar_t,class
ATL::ChTraitsCRT<wchar_t> > >::~CStringT<wchar_t,class
ATL::StrTraitATL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > >(void)"
(??1?$CStringT@_WV?$StrTraitATL@_WV?$ChTraitsCRT@_W@ATL@@@ATL@@@ATL@@QAE@XZ)
already defined in AdminMsgs.obj
ServerEngine.lib(ServerEngine.dll) : error LNK2005: "public: __thiscall
ATL::CSimpleStringT<wchar_t,0>::operator wchar_t const *(void)const "
(??B?$CSimpleStringT@_W$0A@@ATL@@QBEPB_WXZ) already defined in AdminMsgs.obj
ServerEngine.lib(ServerEngine.dll) : error LNK2005: "public: class
ATL::CStringT<wchar_t,class ATL::StrTraitATL<wchar_t,class
ATL::ChTraitsCRT<wchar_t> > > & __thiscall ATL::CStringT<wchar_t,class
ATL::StrTraitATL<wchar_t,class ATL::ChTraitsCRT<wchar_t> >
>::operator=(class ATL::CStringT<wchar_t,class
ATL::StrTraitATL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > > const &)"
(??4?$CStringT@_WV?$StrTraitATL@_WV?$ChTraitsCRT@_W@ATL@@@ATL@@@ATL@@QAEAAV01@ABV01@@Z)
already defined in ErrorLogOptionsDlg.obj
ServerEngine.lib(ServerEngine.dll) : error LNK2005: "public: __thiscall
ATL::CStringT<wchar_t,class ATL::StrTraitATL<wchar_t,class
ATL::ChTraitsCRT<wchar_t> > >::CStringT<wchar_t,class
ATL::StrTraitATL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > >(void)"
(??0?$CStringT@_WV?$StrTraitATL@_WV?$ChTraitsCRT@_W@ATL@@@ATL@@@ATL@@QAE@XZ)
already defined in AdminMsgs.obj
http://msdn2.microsoft.com/en-us/library/ms174286(VS.80).aspx
> Is there any other way to use CString in a DLL.
Would it be possible for you to *not* using CString at the DLL interface?
i.e. you can use CString inside the DLL, but you may consider using wchar_t*
at the DLL interface.
Giovanni
Eric
"Giovanni Dicanio" <giovanni...@invalid.com> wrote in message
news:u07652je...@TK2MSFTNGP04.phx.gbl...
To begin, use the following exporting technique. Replace your direct use of
the __declspec with X_EXPORT, replacing "X" with the name of your DLL,
making sure it has a reasonable chance of being unique:
#ifdef COMPILING_X_DLL
#define X_EXPORT __declspec(dllexport)
#else
#define X_EXPORT __declspec(dllimport)
#endif
Then #define COMPILING_X_DLL only in that DLL's project. This method can be
used by multiple DLLs, and since the macro names are unique, they don't
conflict.
Also, CString has no virtual functions and thus is not a good candidate for
public derivation. Consider using plain old CString and extending its
interface through non-member functions.
Finally, if you want to stick with CStringWEx, try to reproduce the problem
in a minimal DLL consisting of two files, a.cpp and b.cpp, which you can
compile at the command line with:
cl -LD -MD -D_AFXDLL a.cpp b.cpp
If you don't discover the solution along the way, post the files here,
including the definition of CStringWEx.
--
Doug Harrison
Visual C++ MVP
Thanks,
EricW
http://msdn2.microsoft.com/en-us/library/ms174286(VS.80).aspx
"Doug Harrison [MVP]" <d...@mvps.org> wrote in message
news:u23es3leac5lr2l8p...@4ax.com...
>Hi Doug,
> I went with the solution of deriving a new class from CString because the
>MSDN article below suggested that is the best approach.
It isn't for the reason I gave.
>It also seemed to
>suggest the changing of atlstr.h/afxstr.h was required to make this work
>completely which I'd greatly prefer not to do but without that you'll get
>duplicate definitions.
You should have listened to your instinct. :)
>Also I did do something like you suggested in making
>a macro for __declspec( ? ) originally I just left it out for time. Anyway,
>I think I can live with the solution of modifying atlstr.h for now until
>something better comes along.
The only reason I would ever touch a standard header would be to fix a bug,
and even then, I'd look long and hard for a workaround that does not
require touching a standard header. It appears you're doing this not to fix
a bug, but to derive a new class, like it's a standard design technique;
it's not. Besides having to figure out these linker errors you're getting
now, you're creating a maintenance nightmare, because you're going to have
to alter this header every time you install VC, inspect it after applying
service packs, and so forth, and anyone you give your code to will have to
do the same thing. Then are the compatibility problems you may
inadvertently introduce.
>Thanks,
>EricW
>
>
>http://msdn2.microsoft.com/en-us/library/ms174286(VS.80).aspx
The only advice on that page that may be worth taking is, "For more
information on this issue, see the Knowledge Base article, "Linking Errors
When you Import CString-derived Classes" (Q309801)"
http://support.microsoft.com/kb/309801
At least it tells you to modify your stdafx.h file instead of a standard
header. Both articles use the wrong macro for selecting the __declspec
flavor, the MSDN article using AFX_EXT_CLASS, and the KB article _USRDLL;
see my previous message for the one correct method. Again, your best bet is
to forget about deriving from CString and extend its interface through
non-member functions.
--
"EricW" <em...@empty.com> wrote in message
news:%23RaJfBk...@TK2MSFTNGP05.phx.gbl...
I do agree.
Giovanni
Thanks again,
Eric
"Doug Harrison [MVP]" <d...@mvps.org> wrote in message
news:77aes3p18ggv0jqhp...@4ax.com...
>Hi All,
> Thanks for the feedback. While I did get it to work (yes, by modifying
>atlstr.h, ick) I'm going to back off of it for many of the reasons you
>pointed out and try the stdafx.h approach. I've never changed a standard
>header file to fix a problem and I don't want to start now. If you happen
>to know anyone on the compiler team and can give them a nudge to smooth out
>STL and DLL interaction that would be great,... yeah, I know I'm dreaming
>there :).
>
>Thanks again,
>Eric
There haven't been any problems with STL and DLLs since VS.NET 2002, or
even VC6 after applying the Dinkumware patches. I'm really perplexed by
this documentation you found. I would have thought that MFC would dllexport
the most frequently used specializations of CString on char and wchar_t
anyway. What happens if you do nothing at all to "fix" things?
It seems to me that the "auto-exporting" of template base classes
introduced in VC7 to avoid the usually pointless C4275 warning has caused
nothing but problems while "solving" problems that simply do not arise if
you follow these rules for sharing C++ classes and objects across module
boundaries:
1. Link all participating modules to the same CRT DLL. This way, they share
the same heap, file descriptors, and most other CRT state.
2. Treat it as equivalent to static linking WRT things like compiler
version, compiler options, compilation dependencies, and so forth.
3. Don't use templates that have static data without explicitly
instantiating and dllexporting the specializations you use.
Following these rules will allow you to compose programs from DLLs and use
the classes they define as real C++ classes instead of COM-like interfaces.
I don't see how the auto-exporting of template bases does anything useful,
because you can't control precisely which module exports them. I mean, you
can still easily end up with multiple copies of a template specialization
when more than one DLL uses it, which is not a problem if you follow the
rules above; in particular, auto-exporting doesn't solve (3). IIRC, the
real goal was to suppress C4275, but it's always been possible to suppress
C4275 with #pragma warning(disable), which is fine to use, along with
suppressing C4251, if you follow these rules.