Link Error 2028 2029 when using CString in C++/CLI

S

sebastian.dau

Hello Newsgroup,

I have a link error that I did not manage to fix.

I basically consume a VC 8.0 C++ dll that exports a class with a
method containing CString declaration as follows:

class WarnErr
{
//...
CString WarnErr::getReadableCode (long nCode)
{
//...
}

When using the method in another project (C++/CLI) to write a RTCW,
the linker fails with the following error:

Error 2 error LNK2028: unresolved token (0A00000F) "public: static
class ATL::CStringT<char,class StrTraitMFC_DLL<char,class
ATL::ChTraitsCRT<char> > > __cdecl
lala_McsOOP::WarnErr::getReadableCode(long)" (?
getReadableCode@WarnErr@lala_McsOOP@@$$FSA?AV?$CStringT@DV?
$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@J@Z) referenced in
function "public: class System::String ^ __clrcall
lala::Spectrometer::RTCW::SpectrometerException::ToString(void)" (?
ToString@SpectrometerException@RTCW@Spectrometer@lala@@$$FQ$AAMP
$AAVString@System@@XZ) SpectrometerException.obj


Does anybody know how to fix this issue. Or is there any other good
practice passing strings from unmanaged libs tto managed libs?

Thanks for your help!
 
B

Ben Voigt [C++ MVP]

When using the method in another project (C++/CLI) to write a RTCW,
the linker fails with the following error:

Error 2 error LNK2028: unresolved token (0A00000F) "public: static
class ATL::CStringT<char,class StrTraitMFC_DLL<char,class
ATL::ChTraitsCRT<char> > > __cdecl
lala_McsOOP::WarnErr::getReadableCode(long)" (?
getReadableCode@WarnErr@lala_McsOOP@@$$FSA?AV?$CStringT@DV?
$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@J@Z) referenced in
function "public: class System::String ^ __clrcall
lala::Spectrometer::RTCW::SpectrometerException::ToString(void)" (?
ToString@SpectrometerException@RTCW@Spectrometer@lala@@$$FQ$AAMP
$AAVString@System@@XZ) SpectrometerException.obj


Does anybody know how to fix this issue. Or is there any other good
practice passing strings from unmanaged libs tto managed libs?

I suggest that the only things you should pass across module boundaries are:
(1) blocks of raw data (pointer and length)
(2) interface pointers
DCOM shows that by following these two rules you can have very powerful yet
stable interaction between all kinds of different components. Decoupling in
this way is also good for encapsulation, testability, and stability.

Trying to share class objects between unmanaged modules usually fails due to
ODR violations.
 
S

sebastian.dau

I suggest that the only things you should pass across module boundaries are:
(1) blocks of raw data (pointer and length)
(2) interface pointers
DCOM shows that by following these two rules you can have very powerful yet
stable interaction between all kinds of different components. Decoupling in
this way is also good for encapsulation, testability, and stability.

Trying to share class objects between unmanaged modules usually fails due to
ODR violations.

Hello Ben,

thanks for your comment on this issue. I generally agree with your
opinion as it is good practice.
However, there a couple of good reasons for CString as well and I was
under the opinion that passing basic types like strings isn't a big
deal anymore.
Let us consider the lib I'm trying to incorporate with is sort of fix
and will only get subject for changes if any other approach fails.

Can you point me to pretty good practices of passing strings of
individual length's from unmanaged code to C++/CLI code?

Thanks again,

Sebastian Dau
 
B

Ben Voigt [C++ MVP]

Does anybody know how to fix this issue. Or is there any other good
Hello Ben,

thanks for your comment on this issue. I generally agree with your
opinion as it is good practice.
However, there a couple of good reasons for CString as well and I was
under the opinion that passing basic types like strings isn't a big
deal anymore.
Let us consider the lib I'm trying to incorporate with is sort of fix
and will only get subject for changes if any other approach fails.

Can you point me to pretty good practices of passing strings of
individual length's from unmanaged code to C++/CLI code?

First up, you must compile all code using the unmanaged DLL's classes
without /clr and with the same compiler version used by the DLL. Otherwise
the ODR is violated. This is not a recommendation, it is an absolute
requirement to get any sort of reasonable behavior.

Next, you should use fundamental types such as wchar_t* or char* to pass
data between those files compiled without /clr and the ones compiled with.
The definition of those types aren't changed by /clr or the compiler
version. These convert to and from the std::string and CString variants in
the usual way.

Then, use the following functions to get the data to/from .NET
System::String:

PtrToStringChars
System::Runtime::InteropServices::Marshal::ptrToString{Ansi|Auto|BSTR|Uni}

If you do that, everything should link and run without problems. If the DLL
was compiled using an earlier version of the compiler, then the static lib
wrappers described in "First up" should use extern "C" functions. You
should probably do that anyway.
 
S

sebastian.dau

First up, you must compile all code using the unmanaged DLL's classes
without /clr and with the same compiler version used by the DLL. Otherwise
the ODR is violated. This is not a recommendation, it is an absolute
requirement to get any sort of reasonable behavior.

Next, you should use fundamental types such as wchar_t* or char* to pass
data between those files compiled without /clr and the ones compiled with.
The definition of those types aren't changed by /clr or the compiler
version. These convert to and from the std::string and CString variants in
the usual way.

Then, use the following functions to get the data to/from .NET
System::String:

PtrToStringChars
System::Runtime::InteropServices::Marshal::ptrToString{Ansi|Auto|BSTR|Uni}

If you do that, everything should link and run without problems. If the DLL
was compiled using an earlier version of the compiler, then the static lib
wrappers described in "First up" should use extern "C" functions. You
should probably do that anyway.

Thanks, Ben I'll give that a try and see how it works.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top