Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O Visual C++ permite o acesso a recursos do .NET por meio de tipos gerenciados, que fornecem suporte para recursos do Common Language Runtime e estão sujeitos às vantagens e restrições do tempo de execução.
Tipos gerenciados e a função principal
Quando se escreve uma aplicação usando /clr, os argumentos da função main() não podem ser de um tipo gerido.
Um exemplo de assinatura adequada é:
// managed_types_and_main.cpp
// compile with: /clr
int main(int, char*[], char*[]) {}
Equivalentes do .NET Framework a tipos nativos do C++
A tabela a seguir mostra as palavras-chave para tipos internos do Visual C++, que são aliases de tipos predefinidos no namespace System .
| Tipo Visual C++ | Tipo do .NET Framework |
|---|---|
void |
System.Void |
bool |
System.Boolean |
signed char |
System.SByte |
unsigned char |
System.Byte |
wchar_t |
System.Char |
short e signed short |
System.Int16 |
unsigned short |
System.UInt16 |
int, signed int, longe signed long |
System.Int32 |
unsigned int e unsigned long |
System.UInt32 |
__int64 e signed __int64 |
System.Int64 |
unsigned __int64 |
System.UInt64 |
float |
System.Single |
double e long double |
System.Double |
Para obter mais informações sobre a opção do compilador para padrão signed char ou unsigned char, consulte /J (Tipo padrão char é unsigned).
Questões de versão para tipos de valor aninhados em tipos nativos
Considere um módulo de assembly assinado (nome forte) usado para criar um assembly cliente. O componente contém um tipo de valor que é usado no cliente como o tipo para um membro de uma união nativa, uma classe ou uma matriz. Se uma versão futura do componente alterar o tamanho ou o layout do tipo de valor, o cliente deve ser recompilado.
Crie um arquivo de chave com sn.exe (sn -k mykey.snk).
Exemplo
Este é o exemplo do 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 exemplo é o 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();
}
O exemplo produz esta saída:
S.i = 5
S.i = 6
S.i = 10
S.i = 11
Observações
No entanto, se você adicionar outro membro a struct S in nested_value_types.cpp (por exemplo, double d;) e recompilar o componente sem também recompilar o cliente, o resultado será uma exceção não tratada (do tipo System.IO.FileLoadException).
Como testar a igualdade
No exemplo a seguir, um teste de igualdade que usa Extensões Geridas para C++ é baseado no que os handles se referem.
Exemplo
// mcppv2_equality_test.cpp
// compile with: /clr /LD
using namespace System;
bool Test1() {
String ^ str1 = "test";
String ^ str2 = "test";
return (str1 == str2);
}
O IL para este programa mostra que o valor de retorno é implementado usando uma chamada para op_Equality.
IL_0012: call bool [mscorlib]System.String::op_Equality(string, string)
Como diagnosticar e corrigir problemas de compatibilidade de montagem
Quando a versão de um assembly referenciada em tempo de compilação não corresponde à versão do assembly referenciada em tempo de execução, vários problemas podem ocorrer.
Quando um conjunto é compilado, outros conjuntos podem ser referenciados com a sintaxe #using. Durante a compilação, esses assemblies são acessados pelo compilador. As informações desses assemblies são usadas para tomar decisões de otimização.
No entanto, se o assembly referenciado for alterado e recompilado, recompile também o assembly de referência que depende dele. Caso contrário, as assemblagens poderão tornar-se incompatíveis. As decisões de otimização que eram válidas no início podem não estar corretas para a nova versão do assembly. Vários erros de tempo de execução podem ocorrer devido a essas incompatibilidades. Não há nenhuma exceção específica produzida nesses casos. A maneira como a falha é relatada no tempo de execução depende da natureza da alteração de código que causou o problema.
Esses erros não devem ser um problema em seu código de produção final, desde que todo o aplicativo seja reconstruído para a versão lançada do seu produto. As montagens liberadas ao público devem ser identificadas por um número de versão oficial, para que esses problemas sejam evitados. Para obter mais informações, consulte Assembly Versioning.
Para diagnosticar e corrigir um erro de incompatibilidade
Você pode encontrar exceções de tempo de execução ou outras condições de erro no código que faz referência a outro assembly. Se não for possível identificar outra causa, o problema pode ser uma montagem desatualizada.
Primeiro, isole e reproduza a exceção ou outra condição de erro. Um problema que ocorre devido a uma exceção desatualizada deve ser reproduzível.
Verifique o carimbo de data/hora de todos os assemblies referenciados em seu aplicativo.
Se os carimbos de data/hora de quaisquer assemblies referenciados forem posteriores ao carimbo de data/hora da última compilação do aplicativo, o aplicativo estará desatualizado. Se estiver desatualizado, recompile seu aplicativo com os assemblies mais recentes e edite seu código, se necessário.
Execute novamente o aplicativo, execute as etapas que reproduzem o problema e verifique se a exceção não ocorre.
Exemplo
O programa a seguir ilustra o problema: ele primeiro reduz a acessibilidade de um método e, em seguida, tenta acessar esse método em outro assembly sem recompilar. Compile changeaccess.cpp primeiro. É a montagem referenciada que será alterada. Em seguida, compile referencing.cpp. Deve compilar com sucesso. Em seguida, reduza a acessibilidade do método chamado. Recompile changeaccess.cpp com a opção /DCHANGE_ACCESSdo compilador . Faz com que o método access_me seja protected, em vez de public, de modo que não possa ser chamado fora de Test ou dos seus derivados. Sem recompilar referencing.exe, execute novamente o aplicativo. A MethodAccessException ocorre.
// 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;
}
};
Aqui está a fonte para a assemblagem de referência:
// 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;
}
Ver também
Programação .NET com C++/CLI (Visual C++)
Interoperabilidade com outras linguagens .NET (C++/CLI)
Tipos gerenciados (C++/CLI)
#using diretiva