Compartir vía


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 a FromName 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 el FromName 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 /clrconfiguraciones 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

/clrpuede 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:

Consulte también

Ensamblados mixtos (nativos y administrados)