When "It just works!" doesn't. :(

Hi,

To test out "C++ Interop", I created a static library in VC++ 6.0:

Here is the contents of the header file (staticLibrary.h):

#ifndef STATICLIBTEST_H
#define STATICLIBTEST_H

#include <string>

using std::string;

int add352(int value);

string sayHello(string name);

#endif


Here is the implementation (staticLibrary.cpp):

#include "staticLibrary.h"

int add352(int value)
{
return value + 352;
}

string sayHello(string name)
{
string s1("Hello, you are the greatest, ");

return (s1 + name + "!\n");
}

This code compiles fine in VC++ 6.0 and it produces an object called "staticLibrary.lib"

I then started up another VC++ 6.0 project that links to the library, calls one of its function (sayHello) and it works as expected.

Now, I start up Visual C++ Express to test out the exciting C++ Interop capability that allows you to link to legacy libraries. In the project settings, I included the path to the header file (under Additional Include Directories) and the path to the library (under Additional Library Directories).

In my C++/CLI code, I added the statement:

#include "staticLibrary.h"

Then I have the following code:

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {

txtFunctionOut->Text = add352(System::Int32::Parse(txtFunctionIn->Text)).ToString();

}

When building this project, I get the following error message from the linker:

1>StaticLib.lib(staticLibrary.obj) : error LNK2019: unresolved external symbol "void __cdecl std::_Xlen(void)" ( _Xlen@std@@YAXXZ) referenced in function "private: bool __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Grow(unsigned int,bool)" ( _Grow@ $basic_string@DU $char_traits@D@std@@V $allocator@D@2@@std@@AAE_NI_N@Z)
1>StaticLib.lib(staticLibrary.obj) : error LNK2019: unresolved external symbol "void __cdecl std::_Xran(void)" ( _Xran@std@@YAXXZ) referenced in function "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > & __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::assign(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,unsigned int,unsigned int)" ( assign@ $basic_string@DU $char_traits@D@std@@V $allocator@D@2@@std@@QAEAAV12@ABV12@II@Z)

Now, if I comment out the function "sayHello()" then it compiles without errors and runs. So, it seems I am having problems using the standard C++ "string" class. I have tried playing around with the project settings but nothing has helped. Does anyone have any idea what is causing this linker error

Thanks for any help or information!





Answer this question

When "It just works!" doesn't. :(

  • randomblink

    Are you able to single step through the code without any errors Does the sayHello function work

    I ask because I just rebuilt the static library without the /CLR switch and then rebuilt the application with the /CLR switch.

    This time, I got a clean build but when I executed it I got the following error:

    'DotNetApp.exe': Loaded 'C:\Documents and Settings\mong1\My Documents\Visual Studio 2005\Projects\DotNetApp\debug\DotNetApp.exe', Symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\ntdll.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\mscoree.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\kernel32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\advapi32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\rpcrt4.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_0de06acd\msvcr80.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\msvcrt.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_0de06acd\msvcm80.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\ole32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\gdi32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\user32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\WinSxS\x86_Microsoft.VC80.DebugCRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_f75eb16c\msvcp80d.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\WinSxS\x86_Microsoft.VC80.DebugCRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_f75eb16c\msvcr80d.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\AMInit.dll', Binary was not built with debug information.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\wmfhotfix.dll', Binary was not built with debug information.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\shlwapi.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\Program Files\Webroot\Enterprise\Spy Sweeper\sis.dll', Binary was not built with debug information.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\comdlg32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\comctl32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\shell32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\oleaut32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\version.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\wsock32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\ws2_32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\ws2help.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.2180_x-ww_a84f1ff9\comctl32.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Culture.dll', No symbols loaded.
    'DotNetApp.exe': Unloaded 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Culture.dll'
    'DotNetApp.exe': Loaded 'C:\WINDOWS\assembly\NativeImages_v2.0.50727_32\mscorlib\3bff3416cc5b17429de988a052f89be2\mscorlib.ni.dll', No symbols loaded.
    'DotNetApp.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll', No symbols loaded.
    'DotNetApp.exe' (Managed): Loaded 'c:\documents and settings\mong1\my documents\visual studio 2005\projects\dotnetapp\debug\DotNetApp.exe', Symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorjit.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\diasymreader.dll', No symbols loaded.
    'DotNetApp.exe': Loaded 'C:\WINDOWS\system32\rsaenh.dll', No symbols loaded.
    'DotNetApp.exe' (Managed): Loaded 'C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_0de06acd\msvcm80.dll', No symbols loaded.
    First-chance exception at 0x104817fd in DotNetApp.exe: 0xC0000005: Access violation writing location 0x0000000f.
    A buffer overrun has occurred in DotNetApp.exe which has corrupted the program's internal state. Press Break to debug the program or Continue to terminate the program.

    For more details please see Help topic 'How to debug Buffer Overrun Issues'.






  • shakalama

    I'm confused. It did work with VS C++ 6.0.

    I created another project in VS C++ 6.0 that is a console application and I linked it to the static library and I was able to call "sayHello()" and it worked.

    If I comment out the sayHello() function and just leave add352() in the static library then it also works with an application written in VS C++ 2005.

    I thought C++ interop (IJW) is supposed to allow you to link to a legacy native library as if you are working in standard C++.

    I'm confused by what you mean by "depending on the CRT from 6.0 and 8.0. If I recompile the static library with VS C++ 2005, does that make the static library now depend on CRT 8.0 and it will then work


  • thedo

    When you say "use the same programming environment for all modules involved", is that the same thing as saying "all modules have been compiled by the same compiler"


  • Nubby

    Visual C++ has never supported mixing different versions of the C or C++ runtime in the same application - which is what your application is attempting to do.

  • Dietz

    Well, I recompiled the static native library in Visual Studio 2005.

    I set the compiler option for the runtime library to "Multi-thread DLL" and to produce a static library.

    So, now the static native library is dependent on the same CRT as my main application.

    Then I created a new project in C++/CLI with the /CLI option that links to the static native library.

    I am still having problems getting it to compile. If I comment out the sayHello() function from the static native library then it seems to work. If I have the sayHello() function in there, I get unresolved externals when trying to link to it.

    My question is: Is there some kind of limitation on using types such as the std:Strings class as a parameter to external library functions

    If I bring all the source code (library, main application etc) into one project, then it compiles and seems to work.

  • Justin Pyfrom

    IJW also works with static libs. I managed to do that. But it is essential, that you use the same programming environment for all modules involved.
  • janetfan95758

    Okay, this is odd.

    If I switch the project settings to use "Multiithreaded DLL Debug", on all my modules (instead of just Multithreaded DLL) then it seems to work!

    So, I have a static native library that is compiled without the /CLR option that represents native legacy code.

    Then I have a legacy native application that uses this library. I just compile the application (without the /CLR option) in VS 2005 and link with the library and it seems to work!

    Then I also have a new C++/CLI application that also uses this static library. All I do is compile (with the /CLR option) and link it with the static library and it seems to work!

    This is what I was hoping for when I read about "It Just Works".

    I was hoping that all we needed to do was to recompile our legacy code with the new VS 2005 compiler and keep it as native code (static LIB etc).

    Then we would write a managed C++/CLR wrapper that links to the static native library and act as a proxy to any other .NET language.  This will allow our future .NET based code to use our legacy libraries.

    At the same time, our legacy applications will continue to work with our legacy libraries.

    So, if this continues to work, then I will be very happy.

    BTW, one odd thing I noticed is that after the return from sayHello(), the string that was returned seemed to have a square appended at the end (is it the NULL terminator ).


  • 2162

    I followed the steps of repro, but unfortunately I get a clean build. The code does look like a legacy code, but it should still compile. You may try using ildasm to figure out what exactly is wrong with metadata. You may find some more information in http://msdn2.microsoft.com/en-US/library/zkf0dz41.aspx.

    Also you may not need to recompile your legacy code with /clr. Pick parts of your application that are going to use managed code and only recompile those parts. Throwing /clr on all application is a bad idea in many cases. Keep /clr only to parts when you see clear benefit of using managed code and there is simple alternative solution that can be implemented using native code.

    Nikola



  • zeljko62

    I am not sure what the issue is exactly because I do not see what errors are issue by the compiler or linker. However using std::string as a return parameter from a static library should not be an issue. It is not a good practice, but it should work fine.

    Nikola



  • arashikage

    Okay, I re-read that article on "It Just Works" on www.codeguru.com site and I misread it. It only works if the library is a DLL as you said. For some reason I thought it would work as a static library.

    But just to clear things up, am I correct to think that static linking should work if I recompile the code with VS C++ 2005 Thanks.


  • xboxracer

    Jonathan is absolutely right. You are creating static library that depends on CRT from 6.0 and attempting to link it with the code that depends on CRT 8.0. This is not going to work. It has nothing to do with IJW, it does not work in native code also. If you would like to build a module that can be used with different versions of CRT, it has to be build as a DLL with exports that obey rules of data passing across DLL boundary.

    Nikola



  • Nick Hart

    All the errors go away if I remove all code that uses std::string.

    I have tried many permutations in trying to get this work. I even have tried just working in pure native mode (in other words, using VS 2005 as if it were VS 6.0) and I still get linker errors.

    If I combine all the source code (library and application) into one project, it seems to work. So, it almost seems like I can't pass std::strings as parameters if the static library is an external file.

    Oh, I guess I should mention that I've been doing my testing with Visual Studio C++ 2005 Express (instead of VS 2005) but I didn't think that should make any difference





  • JohnWP

    Here is what I'm currently experiencing (I've been playing around with different configurations and settings in trying to get this to work):

    This is supposed to represent old legacy C/C++ code that I want to migrate to C++/CLI.

    So, I take this old code and recompile with VS C++ 2005. The old code looks like this:

    Here is the header file

    #ifndef STATICLIBTEST_H
    #define STATICLIBTEST_H

    #include <string>
    using std::string;

    int add352(int value);

    string sayHello(string name);

    #endif

    Here is the source file:

    #include "staticLibrary.h"

    int add352(int value)
    {
    return value + 352;
    }

    string sayHello(string name)
    {
    string s1("Hello, you are the greatest, ");

    return (s1 + name + "!\n");
    }


    This has been compiled with VS 2005 with the /CLR switch, Multithread DLL and produces a LIB file called "StaticLibDotNet.lib"

    I now create the following C++/CLR console application that will link to this static library:

    // DotNetApp.cpp : main project file.

    #include "stdafx.h"
    #include "staticLibrary.h"

    using namespace System;

    int main(array<System::String ^> ^args)
    {
    int a = add352(27);

    string s;
    string name = "John";

    s = sayHello(name);

    return 0;
    }


    In the project settings, I have the additional include and library directories pointing to the correct locations. In the additional dependencies, I have added "StaticLibDotNet.lib". I have it set to compile with the /CLR switch and Multithreaded DLL. When I try to compile, I get the following errors:

    1>------ Rebuild All started: Project: DotNetApp, Configuration: Debug Win32 ------
    1>Deleting intermediate and output files for project 'DotNetApp', configuration 'Debug|Win32'
    1>Compiling...
    1>stdafx.cpp
    1>Compiling...
    1>DotNetApp.cpp
    1>AssemblyInfo.cpp
    1>Generating Code...
    1>Compiling resources...
    1>Linking...
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.ostreambuf_iterator<char,std::char_traits<char> >): (0x0200000f).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.ostreambuf_iterator<wchar_t,std::char_traits<wchar_t> >): (0x02000010).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.logic_error): (0x02000019).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.basic_string<char,std::char_traits<char>,std::allocator<char> >): (0x0200001a).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.domain_error): (0x0200001c).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.invalid_argument): (0x0200001d).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.length_error): (0x0200001e).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.out_of_range): (0x0200001f).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.runtime_error): (0x02000020).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.overflow_error): (0x02000021).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.underflow_error): (0x02000022).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.range_error): (0x02000023).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._Locinfo): (0x02000025).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (_Locimp): (0x0200002b).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (failure): (0x02000037).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >): (0x02000048).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._String_val<char,std::allocator<char> >): (0x02000058).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.istreambuf_iterator<char,std::char_traits<char> >): (0x02000059).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.istreambuf_iterator<wchar_t,std::char_traits<wchar_t> >): (0x0200005a).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._String_val<wchar_t,std::allocator<wchar_t> >): (0x0200005e).
    1>StaticLibDotNet.lib(staticLibrary.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._Iterator_base): (0x0200007a).
    1>LINK : fatal error LNK1255: link failed because of metadata errors
    1>Build log was saved at "file://c:\Documents and Settings\mong1\My Documents\Visual Studio 2005\Projects\DotNetApp\DotNetApp\Debug\BuildLog.htm"
    1>DotNetApp - 22 error(s), 0 warning(s)
    ========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

    Any help would be greatly appreciated. I've been working on trying to understand this material (because I was tasked with researching the best approach on migrating our legacy code base to .NET) and it's been frustrating. The concepts seem pretty straight forward but I can't get my simple examples to work in order to verify my understanding.




  • When "It just works!" doesn't. :(