Tipos administrados (C++/CLI)
Visual C++ permite el acceso a las características de .NET a través de tipos administrados, que proporcionan compatibilidad con las características de Common Language Runtime y están sujetas a las ventajas y restricciones del runtime.
Tipos administrados y la función main
Al escribir una aplicación mediante /clr , los argumentos de la /clr no pueden ser de un tipo administrado.
Un ejemplo de una firma adecuada es:
// managed_types_and_main.cpp
// compile with: /clr
int main(int, char*[], char*[]) {}
.Equivalentes de .NET Framework para tipos nativos de C++
En la tabla siguiente se muestran las palabras clave para los tipos Visual C++ integrados, que son alias de tipos predefinidos en el espacio de nombres System.
| Visual C++ tipo | Tipo de .NET Framework |
|---|---|
void |
System.Void |
bool |
System.Boolean |
signed char |
System.SByte |
unsigned char |
System.Byte |
wchar_t |
System.Char |
short y signed short |
System.Int16 |
unsigned short |
System.UInt16 |
int, signed int, long y signed long. |
System.Int32 |
unsigned int y unsigned long |
System.UInt32 |
__int64 y signed __int64 |
System.Int64 |
unsigned __int64 |
System.UInt64 |
float |
System.Single |
double y long double |
System.Double |
Para obtener más información sobre la opción del compilador para el valor predeterminado signed char o unsigned char , vea signed char
Problemas de versión con tipos de valor anidados en tipos nativos
Considere la posibilidad de usar un componente de ensamblado con firma (nombre fuerte) para compilar un ensamblado de cliente. El componente contiene un tipo de valor que se usa en el cliente como tipo para un miembro de una unión nativa, una clase o una matriz. Si una versión futura del componente cambia el tamaño o el diseño del tipo de valor, se debe volver a compilar el cliente.
Cree un archivo de claves consn.exe ( ).
Ejemplo
El ejemplo siguiente es el componente .
// nested_value_types.cpp
// compile with: /clr /LD
using namespace System::Reflection;
[assembly:AssemblyVersion("1.0.0.*"),
assembly:AssemblyKeyFile("mykey.snk")];
public value struct S {
int i;
void Test() {
System::Console::WriteLine("S.i = {0}", i);
}
};
Este ejemplo es el cliente:
// nested_value_types_2.cpp
// compile with: /clr
#using <nested_value_types.dll>
struct S2 {
S MyS1, MyS2;
};
int main() {
S2 MyS2a, MyS2b;
MyS2a.MyS1.i = 5;
MyS2a.MyS2.i = 6;
MyS2b.MyS1.i = 10;
MyS2b.MyS2.i = 11;
MyS2a.MyS1.Test();
MyS2a.MyS2.Test();
MyS2b.MyS1.Test();
MyS2b.MyS2.Test();
}
El ejemplo produce la siguiente salida:
S.i = 5
S.i = 6
S.i = 10
S.i = 11
Comentarios
Sin embargo, si agrega otro miembro a en nested_value_types.cpp, (por ejemplo, ) y vuelve a compilar el componente sin volver a compilar el cliente, el resultado es una excepción no controlada (de tipo struct Sdouble d;struct S
Cómo: Probar la igualdad
En el ejemplo siguiente, una prueba de igualdad que usa Extensiones administradas para C++ se basa en lo que hacen referencia los identificadores.
Ejemplo
// mcppv2_equality_test.cpp
// compile with: /clr /LD
using namespace System;
bool Test1() {
String ^ str1 = "test";
String ^ str2 = "test";
return (str1 == str2);
}
El IL de este programa muestra que el valor devuelto se implementa mediante una llamada a op_Equality.
IL_0012: call bool [mscorlib]System.String::op_Equality(string,
string)
Cómo: Diagnosticar y resolver los problemas de compatibilidad de los ensamblados
En este tema se explica lo que puede ocurrir cuando la versión de un ensamblado al que se hace referencia en tiempo de compilación no coincide con la versión del ensamblado al que se hace referencia en tiempo de ejecución y cómo evitar el problema.
Cuando se compila un ensamblado, se puede hacer referencia a otros ensamblados con la #using sintaxis . Durante la compilación, el compilador tiene acceso a estos ensamblados. La información de estos ensamblados se usa para tomar decisiones de optimización.
Sin embargo, si se cambia y se vuelve a compilar el ensamblado al que se hace referencia y no se vuelve a compilar el ensamblado de referencia que depende de él, es posible que los ensamblados no sean compatibles. Es posible que las decisiones de optimización que eran válidas al principio no sean correctas con respecto a la nueva versión del ensamblado. Pueden producirse varios errores en tiempo de ejecución debido a estas incompatibilidades. No hay ninguna excepción específica que se produzca en estos casos. La forma en que se notifica el error en tiempo de ejecución depende de la naturaleza del cambio de código que produjo el problema.
Estos errores no deben ser un problema en el código de producción final, siempre y cuando se recompile toda la aplicación para la versión publicada del producto. Los ensamblados que se liberan al público deben marcarse con un número de versión oficial, lo que garantizará que se eviten estos problemas. Para obtener más información, vea Versiones de los ensamblados.
Diagnóstico y corrección de un error de incompatibilidad
Si encuentra excepciones en tiempo de ejecución u otras condiciones de error que se producen en el código que hace referencia a otro ensamblado y no tiene ninguna otra causa identificada, es posible que esté tratando con un ensamblado no actualizado.
En primer lugar, aísle y reproduzca la excepción u otra condición de error. Un problema que se produce debido a una excepción obsoleta debe ser reproducible.
Compruebe la marca de tiempo de los ensamblados a los que se hace referencia en la aplicación.
Si las marcas de tiempo de los ensamblados a los que se hace referencia son posteriores a la marca de tiempo de la última compilación de la aplicación, la aplicación no está actualizada. Si esto ocurre, vuelva a compilar la aplicación con el ensamblado más reciente y realice los cambios de código necesarios.
Vuelva a ejecutar la aplicación, realice los pasos que reproducen el problema y compruebe que no se produce la excepción.
Ejemplo
El programa siguiente ilustra el problema reduciendo la accesibilidad de un método e intentando tener acceso a ese método en otro ensamblado sin volver a compilarlo. Pruebe a compilar changeaccess.cpp primero. Este es el ensamblado al que se hace referencia que cambiará. A continuación, compile referencing.cpp . La compilación se realiza correctamente. Ahora, reduzca la accesibilidad del método llamado. Vuelva a compilar changeaccess.cpp con la marca /DCHANGE_ACCESS . Esto hace que el método esté protegido, en lugar de privado, por lo que ya se puede llamar legalmente. Sin volver a compilar referencing.exe , vuelva a ejecutar la aplicación. Se producirá una excepción MethodAccessException.
// changeaccess.cpp
// compile with: /clr:safe /LD
// After the initial compilation, add /DCHANGE_ACCESS and rerun
// referencing.exe to introduce an error at runtime. To correct
// the problem, recompile referencing.exe
public ref class Test {
#if defined(CHANGE_ACCESS)
protected:
#else
public:
#endif
int access_me() {
return 0;
}
};
// referencing.cpp
// compile with: /clr:safe
#using <changeaccess.dll>
// Force the function to be inline, to override the compiler's own
// algorithm.
__forceinline
int CallMethod(Test^ t) {
// The call is allowed only if access_me is declared public
return t->access_me();
}
int main() {
Test^ t = gcnew Test();
try
{
CallMethod(t);
System::Console::WriteLine("No exception.");
}
catch (System::Exception ^ e)
{
System::Console::WriteLine("Exception!");
}
return 0;
}
Vea también
Programación de .NET con C++/CLI (Visual C++)
Interoperabilidad con otros lenguajes .NET (C++/CLI)
Tipos administrados (C++/CLI)
#using directiva