Cómo: Migrar a /clr
En este artículo se describen los problemas que surgen al compilar código nativo con /clr
. (Para obtener más información, vea /clr (Compilación de Common Language Runtime)). /clr
permite que el código nativo de C++ invoque y se invoque desde ensamblados de .NET, además de otro código nativo de C++. Para obtener más información sobre las ventajas de compilar con /clr
, vea Ensamblados mixtos (nativos y administrados) y interoperabilidad nativa y .NET.
Problemas conocidos al compilar proyectos de biblioteca con /clr
Visual Studio contiene algunos problemas conocidos al compilar proyectos de biblioteca con /clr
:
El código puede consultar tipos en tiempo de ejecución con
CRuntimeClass::FromName
. Sin embargo, si un tipo está en un archivo DLL de MSIL (compilado con/clr
), la llamada aFromName
puede producir un error si se produce antes de que los constructores estáticos se ejecuten en el archivo DLL administrado. (No verá este problema si la llamada se produce después de que elFromName
código se haya ejecutado en el archivo DLL administrado). Para solucionar este problema, puede forzar la construcción del constructor estático administrado: definir una función en el archivo DLL administrado, exportarlo e invocarlo desde la aplicación MFC nativa. Por ejemplo:// MFC extension DLL Header file: __declspec( dllexport ) void EnsureManagedInitialization () { // managed code that won't be optimized away System::GC::KeepAlive(System::Int32::MaxValue); }
Compilar con Visual C++
Antes de usar /clr
en cualquier módulo del proyecto, compile primero y vincule el proyecto nativo con Visual Studio.
Los pasos siguientes, seguidos en orden, proporcionan la ruta de acceso más sencilla a una /clr
compilación. Es importante compilar y ejecutar el proyecto después de cada uno de estos pasos.
Actualización desde versiones anteriores de Visual Studio
Si va a actualizar Visual Studio desde una versión anterior, es posible que vea errores del compilador relacionados con la conformidad de C++ estándar mejorada en Visual Studio.
Los proyectos compilados con versiones anteriores de Visual Studio también deben compilarse primero sin /clr
. Visual Studio ahora ha aumentado la conformidad de C++ estándar y algunos cambios importantes. Los cambios que probablemente requieran la mayor atención son las características de seguridad de CRT. Es probable que el código que usa CRT genere advertencias de desuso. Estas advertencias se pueden suprimir, pero se prefiere migrar a las nuevas versiones mejoradas de seguridad de las funciones de CRT, ya que proporcionan una mejor seguridad y pueden revelar problemas de seguridad en el código.
Actualizar desde Extensiones administradas para C++
En Visual Studio 2005 y versiones posteriores, el código escrito con Extensiones administradas para C++ no se compilará en /clr
.
Conversión de código de C en C++
Aunque Visual Studio compilará archivos de C, es necesario convertirlos en C++ para una /clr
compilación. El nombre de archivo real no tiene que cambiarse; puede usar /Tp
(vea/Tc
, /Tp
, /TC
, /TP
(Especificar el tipo de archivo de origen)). Aunque los archivos de código fuente de C++ son necesarios para /clr
, no es necesario refactorizar el código para usar paradigmas orientados a objetos.
Es probable que el código de C requiera cambios cuando se compile como un archivo de C++. Las reglas de seguridad de tipos de C++ son estrictas, por lo que las conversiones de tipos se deben realizar de forma explícita. Por ejemplo, malloc devuelve un puntero nulo, pero se puede asignar a un puntero de cualquier tipo de C con una conversión:
int* a = malloc(sizeof(int)); // C code
int* b = (int*)malloc(sizeof(int)); // C++ equivalent
Los punteros a función también presentan una seguridad de tipos estricta en C++, por lo que el siguiente código de C requiere alguna modificación. En C++, es mejor crear un typedef
que defina el tipo de puntero de función y, a continuación, usar ese tipo para convertir punteros de función:
NewFunc1 = GetProcAddress( hLib, "Func1" ); // C code
typedef int(*MYPROC)(int); // C++ equivalent
NewFunc2 = (MYPROC)GetProcAddress( hLib, "Func2" );
C++ también requiere que se creen prototipos de las funciones o se definan totalmente para que se pueda hacer referencia a ellas o se puedan invocar.
Se debe cambiar el nombre de los identificadores utilizados en el código de C que resulten ser palabras clave en C++ (como virtual
, new
, delete
, bool
, true
, false
, etc.) Por lo general, este cambio se puede realizar con operaciones simples de búsqueda y reemplazo.
COMObj1->lpVtbl->Method(COMObj, args); // C code
COMObj2->Method(args); // C++ equivalent
Volver a configurar la configuración del proyecto
Después de compilar y ejecutar el proyecto en Visual Studio, debe crear nuevas configuraciones de proyecto para /clr
en lugar de modificar las configuraciones predeterminadas. /clr
no es compatible con algunas opciones del compilador. La creación de configuraciones independientes le permite compilar el proyecto como nativo o administrado. Cuando /clr
se selecciona en el cuadro de diálogo páginas de propiedades, la configuración del proyecto no es compatible con /clr
están deshabilitadas. (Las opciones deshabilitadas no se restauran automáticamente si /clr
no está seleccionada más adelante).
Creación de nuevas configuraciones de proyecto
Puede usar la opción Copiar configuración desde en el cuadro de diálogo Nueva configuración del proyecto (Compilar>Configuration Manager>Configuración de soluciones activas>Nueva) para crear una configuración de proyecto basada en la configuración del proyecto existente. Cree una copia de la configuración una vez para la configuración de depuración y una vez para La configuración de versión. Los cambios posteriores solo se pueden aplicar a las /clr
configuraciones específicas, dejando intactas las configuraciones del proyecto original.
Los proyectos que usan reglas de compilación personalizadas pueden requerir más atención.
Este paso tiene implicaciones diferentes para los proyectos que utilizan archivos Make. En este caso, se puede configurar un destino de compilación independiente o se puede crear una versión específica de la /clr
compilación a partir de una copia del original.
Cambiar la configuración del proyecto
/clr
puede seleccionarse en el entorno de desarrollo siguiendo las instrucciones de /clr (Compilación de Common Language Runtime). Como se mencionó previamente, este paso deshabilitará automáticamente los parámetros de configuración del proyecto en conflicto.
Nota:
Al actualizar una biblioteca administrada o un proyecto de servicio web desde Visual Studio 2003, la /Zl
opción del compilador se agrega a la página de propiedades de la línea de comandos. Esto provoca errores LNK2001. Quite /Zl
de la página de propiedades línea de comandos para resolver los errores. Para obtener más información, consulte /Zl
(Omitir el nombre de biblioteca predeterminado) y Establecer las propiedades del compilador y la compilación.
En el caso de los proyectos creados con archivos make, las opciones del compilador incompatibles deben deshabilitarse manualmente una vez /clr
agregadas. Para obtener información sobre las opciones del compilador que no son compatibles con /clr
, vea /clr
restricciones.
Encabezados precompilados
Los encabezados precompilados se admiten en /clr
. Sin embargo, si solo compila algunos de los archivos CPP con /clr
(compilando el resto como nativo), se requieren algunos cambios. Los encabezados precompilados generados con /clr
no son compatibles con los encabezados precompilados generados sin /clr
, ya que /clr
genera y requiere metadatos. Los módulos compilados con /clr
no pueden usar encabezados precompilados que no incluyan metadatos y/clr
no módulos no pueden usar archivos de encabezado precompilados que contengan metadatos.
La manera más fácil de compilar un proyecto con /clr
el que algunos módulos se compilan consiste en deshabilitar completamente los encabezados precompilados. (En el cuadro de diálogo Páginas de propiedades del proyecto, abra el Nodo C/C++ y seleccione Encabezados precompilados. A continuación, cambie la propiedad Create/Use Precompiled Headers a "Not Using Precompiled Headers" (No usar encabezados precompilados).
Sin embargo, especialmente para proyectos grandes, los encabezados precompilados proporcionan una velocidad de compilación mucho mejor, por lo que no es deseable deshabilitar esta característica. En este caso, es mejor configurar los /clr
archivos y no/clr
para usar encabezados precompilados independientes. Puede configurarlos en un paso: seleccione varios módulos con /clr
los que compilar mediante Explorador de soluciones. Haga clic con el botón derecho en el grupo y seleccione Propiedades. A continuación, cambie las propiedades Create/Use PCH Through File y Precompiled Header File para usar un nombre de archivo de encabezado diferente y un archivo PCH, respectivamente.
Corregir errores
La compilación del código con /clr
puede dar lugar a errores de compilador, enlazador o tiempo de ejecución. En esta sección se describen los problemas más comunes.
Combinación de metadatos
Las distintas versiones de los tipos de datos pueden hacer que el vinculador produzca un error debido a que los metadatos generados para los dos tipos no coinciden. (Los errores se producen cuando se definen condicionalmente miembros de un tipo, pero las condiciones no son las mismas para todos los archivos CPP que usan el tipo). En este caso, se produce un error en el enlazador, notificando solo el nombre del símbolo y el nombre del segundo archivo OBJ donde se definió el tipo. Es posible que le resulte útil rotar el orden en que se envían los archivos OBJ al enlazador para detectar la ubicación de la otra versión del tipo de datos.
Interbloqueo de bloqueo del cargador
Se puede producir el "interbloqueo de bloqueo del cargador", pero es determinista y se detecta y se notifica en tiempo de ejecución. Consulte Inicialización de ensamblados mixtos para obtener información detallada, instrucciones y soluciones.
Exportaciones de datos
La exportación de datos DLL es propensa a errores y no se recomienda en /clr
el código. Esto se debe a que no se garantiza la inicialización de la sección de datos de un archivo DLL hasta que se ejecuta alguna parte administrada del archivo DLL. Metadatos de referencia con #using
directivas.
Visibilidad de tipos
Los tipos nativos son private
de forma predeterminada. Un private
tipo nativo no está visible fuera del archivo DLL. Para resolver este error, agregue public
a estos tipos.
Problemas de alineación y punto flotante
__controlfp
no se admite en Common Language Runtime. (Para obtener más información, vea _control87
, _controlfp
, __control87_2
). ClR tampoco respeta align
.
Inicialización COM
Common Language Runtime inicializa COM automáticamente cuando se inicializa un módulo (cuando SE inicializa COM automáticamente, se hace como MTA). Como resultado, la inicialización explícita de COM produce códigos devueltos que indican que COM ya se ha inicializado. El intento de inicializar COM explícitamente con un modelo de subprocesos cuando CLR ya ha inicializado COM en otro modelo de subprocesos puede hacer que la aplicación no funcione correctamente.
Common Language Runtime inicia COM como MTA de forma predeterminada; use /CLRTHREADATTRIBUTE
(Establezca el atributo de subproceso CLR) para modificar el modelo COM.
Problemas de rendimiento
Es posible que vea una disminución del rendimiento cuando los métodos nativos de C++ generados en MSIL se llaman indirectamente (a través de llamadas de función virtual o mediante punteros de función). Para más información, consulte Double Thunking.
Al pasar de nativo a MSIL, observará un aumento en el tamaño del conjunto de trabajo. Este aumento se produce porque Common Language Runtime proporciona muchas características para asegurarse de que los programas se ejecutan correctamente. Si la /clr
aplicación no se está ejecutando correctamente, es posible que quiera habilitar la advertencia del compilador predeterminada (nivel 1 y 3) C4793.
El programa se bloquea al apagarse
En algunos casos, CLR puede apagarse antes de que finalice la ejecución del código administrado. El uso de std::set_terminate
y SIGTERM
puede provocar el apagado. Para obtener más información, vea signal
constantes y set_terminate
.
Uso de nuevas características de Visual C++
Después de compilar, vincular y ejecutar la aplicación, puede empezar a usar características de .NET en cualquier módulo compilado con /clr
. Para obtener más información, consulta Component Extensions for Runtime Platforms.
Para obtener más información sobre la programación de .NET en Visual C++, vea: