Linker error when using unique_ptr in C ++ / CLI

I am currently converting my auto_ptr instances to unique_ptr , but I have a problem. It works great in terms of C ++ code, but when I do this at my managed C ++ / CLI level (the software uses both C # and C ++), I get link errors. It compiles fine, but it breaks during connection. There were no problems with auto_ptr .

I am currently using Visual Studio 2010. Does anyone know of any problems using unique_ptr in C ++ / CLI?

I tried to summarize my problem with the code below, but remember that the code below really compiles and works (I checked that the ownership of the pointers moves correctly). When compiling, I donโ€™t get the error link, but below is the C ++ code, not the C ++ / CLI. I just wanted to have a minimal example of how the code is generated, so the linker error makes sense to read.

 #include "stdafx.h" #include <vector> #include <memory> #include <utility> using namespace std; namespace Test { template< class T > struct LinAlgPoint3 { LinAlgPoint3() { x = y = z = 0; }; union { struct {T x,y,z;} ; T data_[3]; }; }; class ContainerClass { public: void setUniquePtr( unique_ptr< vector< LinAlgPoint3< float > > > newUniquePtr1 , unique_ptr< vector< unsigned char > > newUniquePtr2 ) { m_uniquePtr1 = move(newUniquePtr1); m_uniquePtr2 = move(newUniquePtr2); } private: unique_ptr< vector< LinAlgPoint3< float > > > m_uniquePtr1; unique_ptr< vector< unsigned char > > m_uniquePtr2; }; int main(int argc, char** argv) { auto pos = unique_ptr< vector< LinAlgPoint3< float > > >( new vector< LinAlgPoint3< float > >() ); auto name = unique_ptr< vector< unsigned char > >(new vector< unsigned char >()); ContainerClass container; container.setUniquePtr(move(pos), move(name)); } } //namespace Test 

The error that occurs when binding is as follows:

 error LNK2028: unresolved token (0A0018A5) "private: __cdecl std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >(class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > const &)" ( ??0?$unique_ptr@V ?$vector@U ?$LinAlgPoint3@M @ Test@ @ V?$allocator@U ?$LinAlgPoint3@M @ Test@ @@ std@ @@ std@ @ U?$default_delete@V ?$vector@U ?$LinAlgPoint3@M @ Test@ @ V?$allocator@U ?$LinAlgPoint3@M @ Test@ @@ std@ @@ std@ @@ 2@ @ std@ @ $$FAEAA@AEBV01 @@Z) referenced in function "public: static void __clrcall std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >::<MarshalCopy>(class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > *,class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > *)" (?<MarshalCopy>@ ?$unique_ptr@V ?$vector@U ?$LinAlgPoint3@M @ Test@ @ V?$allocator@U ?$LinAlgPoint3@M @ Test@ @@ std@ @@ std@ @ U?$default_delete@V ?$vector@U ?$LinAlgPoint3@M @ Test@ @ V?$allocator@U ?$LinAlgPoint3@M @ Test@ @@ std@ @@ std@ @@ 2@ @ std@ @ $$FSMXPEAV12@0 @Z) 1>TestClass.obj : error LNK2028: unresolved token (0A0018A6) "private: __cdecl std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >(class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > const &)" ( ??0?$unique_ptr@V ?$vector@EV ?$allocator@E @ std@ @@ std@ @ U?$default_delete@V ?$vector@EV ?$allocator@E @ std@ @@ std@ @@ 2@ @ std@ @ $$FAEAA@AEBV01 @@Z) referenced in function "public: static void __clrcall std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >::<MarshalCopy>(class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > *,class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > *)" (?<MarshalCopy>@ ?$unique_ptr@V ?$vector@EV ?$allocator@E @ std@ @@ std@ @ U?$default_delete@V ?$vector@EV ?$allocator@E @ std@ @@ std@ @@ 2@ @ std@ @ $$FSMXPEAV12@0 @Z) 1>TestClass.obj : error LNK2019: unresolved external symbol "private: __cdecl std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >(class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > const &)" ( ??0?$unique_ptr@V ?$vector@EV ?$allocator@E @ std@ @@ std@ @ U?$default_delete@V ?$vector@EV ?$allocator@E @ std@ @@ std@ @@ 2@ @ std@ @ $$FAEAA@AEBV01 @@Z) referenced in function "public: static void __clrcall std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >::<MarshalCopy>(class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > *,class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > *)" (?<MarshalCopy>@ ?$unique_ptr@V ?$vector@EV ?$allocator@E @ std@ @@ std@ @ U?$default_delete@V ?$vector@EV ?$allocator@E @ std@ @@ std@ @@ 2@ @ std@ @ $$FSMXPEAV12@0 @Z) 1>TestClass.obj : error LNK2019: unresolved external symbol "private: __cdecl std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >(class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > const &)" ( ??0?$unique_ptr@V ?$vector@U ?$LinAlgPoint3@M @ Test@ @ V?$allocator@U ?$LinAlgPoint3@M @ Test@ @@ std@ @@ std@ @ U?$default_delete@V ?$vector@U ?$LinAlgPoint3@M @ Test@ @ V?$allocator@U ?$LinAlgPoint3@M @ Test@ @@ std@ @@ std@ @@ 2@ @ std@ @ $$FAEAA@AEBV01 @@Z) referenced in function "public: static void __clrcall std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >::<MarshalCopy>(class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > *,class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > *)" (?<MarshalCopy>@ ?$unique_ptr@V ?$vector@U ?$LinAlgPoint3@M @ Test@ @ V?$allocator@U ?$LinAlgPoint3@M @ Test@ @@ std@ @@ std@ @ U?$default_delete@V ?$vector@U ?$LinAlgPoint3@M @ Test@ @ V?$allocator@U ?$LinAlgPoint3@M @ Test@ @@ std@ @@ std@ @@ 2@ @ std@ @ $$FSMXPEAV12@0 @Z) 1>D:\Test\Test.dll : fatal error LNK1120: 4 unresolved externals 

As you can see (if you can go through incredibly awful messages) there are some links to MarshalCopy, which makes me worry that C ++ / CLI does not yet support unique_ptr.

Software layout

 C# executable -> C++/CLI translation layer (dll) -> C++ dll 

Thus, the C ++ dll compiles fine with unique_ptr, but the C ++ / CLI DLL cannot correctly connect.

I forgot to mention something very important: if I use unique_ptr for a simpler data type, like a string, it binds successfully. For example:

  auto string1= unique_ptr< string >(new string(20000, 'S')); auto string2 = unique_ptr< string >(new string(20000, 'A')); string1= std::move(string2); 

and I also tried using a variable so that the compiler does not optimize it.

Edit: I just checked adding another external function that accepts unique_ptr<string> , and I tried to send to string1 above, and that will break too! Thus, the problem should be between the generated DLLs, since std :: move () works well inside each file / class.

+7
source share
3 answers

Well, I donโ€™t know how relevant this is now, but I had exactly the same problem with C ++ / CLI and it was solved using the r-value link instead of the value. I mean: void setUniquePtr (unique_ptr && a, unique_ptr && b)

Thus, it compiles, although this is not the cleanest way to do something.

+8
source

Reading this complex error message, I think he complains that the LinAlgPoint3 framework LinAlgPoint3 not have a copy constructor. Try implementing the copy constructor, and possibly the = and == operators, and see if it fixes this.

+2
source

You cannot pass C ++ objects between DLLs and expect it to work correctly.

The format of the memory may vary in different modules. Different allocators are almost certainly used (this removes any type of C ++ that owns memory, including string , vector and unique_ptr ).

Using pointers for pure virtual base classes can help with this.

Or, if you have the source code for the C ++ part, try linking C ++ and C ++ / CLI into one DLL, rather than referring to C ++ code in a separate DLL.

+1
source

All Articles