2012-09-19 20 views
7

Actualmente estoy convirtiendo mis instancias de auto_ptr a unique_ptr, pero estoy solucionando un problema. Funciona muy bien en la parte C++ del código, pero cuando lo hago en mi capa administrada C++/CLI (el software usa C# y C++) obtengo errores de enlace. Se compila bien, pero se rompe en el momento del enlace. Nunca hubo problemas con auto_ptr.Error de vinculador cuando se utiliza unique_ptr en C++/CLI

Actualmente estoy usando Visual Studio 2010. ¿Alguien sabe de algún problema con el uso de unique_ptr en C++/CLI?

He tratado de resumir mi problema en un fragmento de código a continuación, pero tenga en cuenta que el código de en realidad compila y funciona (he comprobado que la propiedad de los punteros se mueve correctamente). No obtengo errores de enlace al compilar esto, pero el código siguiente es puro C++ y no C++/CLI. Solo quería tener un ejemplo mínimo de cómo se construye el código, por lo que el error del enlazador tiene más sentido para leer.

#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 

El error que consigo cuando se vincula es la siguiente:

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 

Como se puede ver (si se puede conseguir a través de los mensajes increíblemente horrible) hay algunas referencias a MarshalCopy, algo que me hace Preocuparse de que C++/CLI aún no sea compatible con unique_ptr.

El diseño del software es

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

Así que la DLL C++ compila bien utilizando unique_ptr, pero el DLL C++/CLI es incapaz de enlazar correctamente.

Olvidé mencionar algo bastante importante: si uso unique_ptr para un tipo de datos más simple, por ejemplo una cadena, se vincula con éxito. Por ejemplo:

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

y también he intentado asegurarme de usar la variable para que el compilador no la optimice.

Editar: he probado simplemente añadiendo otra función externa que acepta un unique_ptr<string>, y yo probamos el envío de lo anterior string1 y que rompe así! Entonces, el problema debe ser entre las DLL generadas, ya que std :: move() funciona bien dentro de cada archivo/clase.

+0

Es difícil diagnosticar un problema cuando solo vemos los errores, no el código que los creó. Dijiste que este código C++ funciona, pero tu código C++/CLI real no. ¿Puedes escribir algún código de C++/CLI que muestre el problema? –

+0

Puedo intentar ... No escribí mucho C++/CLI desde cero en mis días :) – AzP

+0

Comente todas las llamadas de movimiento para obtener una compilación limpia. La semántica de movimiento es una característica de C++ 11 implementada por el compilador de C++. No por el compilador C++/CLI. Podría publicar en connect.microsoft.com para sacudir ese árbol. –

Respuesta

8

Bueno, no sé cuán relevante es ahora, pero tuve exactamente el mismo problema con C++/CLI y lo resolví tomando la referencia r-value en lugar de valor. Es decir: setUniquePtr vacío (unique_ptr & & una, unique_ptr & & b)

De esta manera se compila a pesar de que no es una forma más limpia de hacer las cosas.

+0

Esto debe marcarse como la respuesta. Funcionó para mí. – AarCee

2

Leyendo a través de ese mensaje de error complejo, creo que se queja de que la estructura LinAlgPoint3 no tiene un constructor de copia. Intente implementar el constructor de copia, y tal vez los operadores = y ==, y vea si eso lo soluciona.

+0

Gracias por una buena sugerencia. Tenías razón, a la clase le faltaba un operador de asignación así como el constructor de copia (ya tenía '=='), pero agregarlos no solucionó el problema ... :( – AzP

+0

Acabo de agregar más información en el Fin de la pregunta – AzP

1

No puede pasar objetos C++ entre DLL y esperar que funcione correctamente.

El diseño de la memoria puede ser diferente en los diferentes módulos. Es casi seguro que se usen diferentes asignadores (esto elimina cualquier tipo de C++ que posea memoria, incluidos string, vector y unique_ptr).

El uso de punteros a clases virtuales virtuales puras puede ayudar con esto.

O, si tiene el código fuente para la parte C++, intente vincular C++ y C++/CLI en una única DLL, en lugar de hacer referencia al código C++ en una DLL separada.

+0

Pero unique_ptr toma un puntero implícito al destructor para poder llamar al correcto según el tipo. – AzP

+0

@AzP: No solo toma un puntero al destructor, sino que está especializado para cada eliminador. causa problemas a través de los límites del módulo. –

Cuestiones relacionadas