2012-09-19 24 views
7

Aktualnie konwertuję moje instancje auto_ptr na unique_ptr, ale mam problem. Działa wspaniale w części kodu C++, ale gdy robię to w mojej zarządzanej warstwie C++/CLI (oprogramowanie wykorzystuje zarówno C#, jak i C++), otrzymuję błędy łącza. Kompiluje się dobrze, ale zrywa czas połączenia. Nigdy nie było żadnych problemów z auto_ptr.Błąd łącznika podczas korzystania z unique_ptr w języku C++/CLI

Aktualnie używam programu Visual Studio 2010. Czy ktoś wie o jakichkolwiek problemach z używaniem unique_ptr w C++/CLI?

Próbowałem podsumować mój problem w kawałku kodu poniżej, ale należy pamiętać, że kod poniżej faktycznie kompiluje i działa (sprawdziłem, czy własność wskaźników została poprawnie przeniesiona). Podczas kompilacji nie pojawiają się błędy łączące, ale poniższy kod to czysty C++, a nie C++/CLI. Chciałem mieć tylko minimalny przykład konstrukcji kodu, więc błąd linkera ma sens.

#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 

Błąd pojawia podczas łączenia jest następujący:

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 &)" ([email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@@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>@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@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 &)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@@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>@[email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@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 &)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@@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>@[email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@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 &)" ([email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@@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>@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@Z) 
1>D:\Test\Test.dll : fatal error LNK1120: 4 unresolved externals 

Jak widać (jeśli można uzyskać poprzez niezwykle strasznych wiadomości) istnieją pewne odniesienia do MarshalCopy, coś, co sprawia mi martwić się, że C++/CLI może jeszcze nie obsługiwać unique_ptr.

Układ oprogramowania jest

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

Więc dll C++ kompiluje grzywny za pomocą unique_ptr, ale dll C++/CLI jest w stanie prawidłowo połączyć.

Zapomniałem wspomnieć o czymś dość ważnym: Jeśli użyję unique_ptr do prostszego typu danych, na przykład do łańcucha, to z powodzeniem łączy. Na przykład:

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

i starałem się również użyć tej zmiennej, aby kompilator jej nie optymalizował.

EDIT: Właśnie testowano dodając inną funkcję zewnętrzną, która akceptuje unique_ptr<string> i próbowałem wysyłanie w powyższym string1 i łamie, jak dobrze! Tak więc problem musi dotyczyć wygenerowanych bibliotek DLL, ponieważ funkcja std :: move() działa dobrze w każdym pliku/klasie.

+0

Trudno jest zdiagnozować problem, gdy widzimy tylko błędy, a nie kod, który je utworzył. Powiedziałeś, że ten kod C++ działa, ale twój rzeczywisty kod C++/CLI tego nie robi. Czy możesz napisać kod C++/CLI, który wykazuje problem? –

+0

Mogę spróbować ... Nie napisałem wiele C++/CLI od podstaw w moich czasach :) – AzP

+0

Skomentuj wszystkie wywołania ruchu, aby uzyskać czystą kompilację. Przenieś semantykę to funkcja C++ 11 zaimplementowana przez kompilator C++. Nie przez kompilator C++/CLI. Możesz wysłać do serwisu connect.microsoft.com, aby wstrząsnąć tym drzewem. –

Odpowiedz

8

Cóż, nie wiem, jak istotne jest teraz, ale miałem dokładnie ten sam problem z C++/CLI i rozwiązałem go, przyjmując wartość odniesienia r-value zamiast wartości. To znaczy: void setUniquePtr (unique_ptr & & A, unique_ptr & & b)

ten sposób kompiluje choć nie jest to najczystszy sposób do robienia rzeczy.

+0

To powinno być oznaczone jako odpowiedź. Praca dla mnie. – AarCee

2

Czytając ten złożony komunikat o błędzie, myślę, że to narzeka, że ​​struktura LinAlgPoint3 nie ma konstruktora kopiowania. Spróbuj zaimplementować konstruktora kopiowania i być może operatorów = i == i zobacz, czy to naprawi.

+0

Dziękuję za dobrą sugestię. Miałeś rację, w klasie brakowało operatora przypisania, a także konstruktora kopii (miało już '=='), ale dodanie go nie rozwiązało problemu .. :( – AzP

+0

Właśnie dodałem trochę więcej informacji Koniec pytania: – AzP

1

Nie można przekazać obiektów C++ między bibliotekami DLL i oczekiwać, że będą działać poprawnie.

Układ pamięci może się różnić w zależności od modułu. Różne alokatory są prawie na pewno używane (to sprowadza każdy typ C++, który jest właścicielem pamięci, w tym string, vector i unique_ptr).

Pomocne może być stosowanie wskaźników do czystych wirtualnych klas bazowych.

Albo, jeśli masz kod źródłowy dla części C++, spróbuj połączyć C++ i C++/CLI do pojedynczej biblioteki DLL, zamiast odwoływania się do kodu C++ w oddzielnej bibliotece DLL.

+0

Ale unique_ptr pobiera niejawny wskaźnik do destruktora, aby móc wywołać właściwy na podstawie typu. – AzP

+0

@AzP: To nie tylko bierze wskaźnik do destruktora, specjalizuje się w każdym z nich. powoduje problemy w obrębie granic modułu –

Powiązane problemy