Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Visual C++ ermöglicht den Zugriff auf .NET-Features über verwaltete Typen, die Unterstützung für Features der Common Language Runtime bieten und den Vorteilen und Einschränkungen der Laufzeit unterliegen.
Verwaltete Typen und die Hauptfunktion
Wenn Sie eine Anwendung mit /clrschreiben, können die Argumente der main() Funktion nicht von einem verwalteten Typ sein.
Ein Beispiel für eine ordnungsgemäße Signatur ist:
// managed_types_and_main.cpp
// compile with: /clr
int main(int, char*[], char*[]) {}
.NET Framework-Entsprechungen mit nativen C++-Typen
In der folgenden Tabelle sind die Schlüsselwörter für integrierte Visual C++-Typen aufgeführt, bei denen es sich um Aliase vordefinierter Typen im Systemnamespace handelt.
| Visual C++-Typ | .NET Framework-Typ |
|---|---|
void |
System.Void |
bool |
System.Boolean |
signed char |
System.SByte |
unsigned char |
System.Byte |
wchar_t |
System.Char |
short und signed short |
System.Int16 |
unsigned short |
System.UInt16 |
int, signed int, long und signed long |
System.Int32 |
unsigned int und unsigned long |
System.UInt32 |
__int64 und signed __int64 |
System.Int64 |
unsigned __int64 |
System.UInt64 |
float |
System.Single |
double und long double |
System.Double |
Weitere Informationen zur Compileroption für Standard signed char oder unsigned char finden Sie unter /J (Standardtyp char ist unsigned).
Versionsprobleme für Werttypen, die in nativen Typen geschachtelt sind
Erwägen Sie eine signierte Assemblykomponente (starker Name), die zum Erstellen einer Clientassembly verwendet wird. Die Komponente enthält einen Werttyp, der im Client als Typ für ein Mitglied einer systemeigenen Union, einer Klasse oder eines Arrays verwendet wird. Wenn eine zukünftige Version der Komponente die Größe oder das Layout des Werttyps ändert, muss der Client neu kompiliert werden.
Erstellen sie eine Schlüsseldatei mit sn.exe (sn -k mykey.snk).
Beispiel
Das folgende Beispiel ist die Komponente.
// 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);
}
};
Dieses Beispiel ist der Client.
// 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();
}
Das Beispiel generiert die folgende Ausgabe:
S.i = 5
S.i = 6
S.i = 10
S.i = 11
Kommentare
Wenn Sie jedoch ein weiteres Element in struct Snested_value_types.cpp hinzufügen (z. B. double d;) und die Komponente neu kompilieren, ohne den Client ebenfalls erneut zu kompilieren, führt das Ergebnis zu einer nicht behandelten Ausnahme vom Typ System.IO.FileLoadException.
So testen Sie auf Gleichheit
Im folgenden Beispiel wird ein Gleichheitstest durchgeführt, der auf verwalteten Erweiterungen für C++ basiert und sich darauf bezieht, worauf die Handles verweisen.
Beispiel
// mcppv2_equality_test.cpp
// compile with: /clr /LD
using namespace System;
bool Test1() {
String ^ str1 = "test";
String ^ str2 = "test";
return (str1 == str2);
}
Die IL für dieses Programm zeigt, dass der Rückgabewert mithilfe eines Aufrufs op_Equalityimplementiert wird.
IL_0012: call bool [mscorlib]System.String::op_Equality(string, string)
Problembehebung und Diagnose von Kompatibilitätsproblemen bei Assemblierungen
Wenn die Version einer Assembly, auf die zur Kompilierungszeit verwiesen wird, nicht mit der Version der Assembly übereinstimmt, auf die zur Laufzeit verwiesen wird, können verschiedene Probleme auftreten.
Wenn eine Assembly kompiliert wird, können auf andere Assemblys mit der #using Syntax verwiesen werden. Während der Kompilierung wird vom Compiler auf diese Assemblys zugegriffen. Informationen aus diesen Assemblys werden verwendet, um Optimierungsentscheidungen zu treffen.
Wenn die referenzierte Assembly jedoch geändert und neu kompiliert wird, kompilieren Sie auch die referenzierende Assembly, die davon abhängig ist. Andernfalls könnten die Assemblies möglicherweise inkompatibel werden. Optimierungsentscheidungen, die zuerst gültig waren, sind möglicherweise für die neue Assemblyversion nicht richtig. Aufgrund dieser Inkompatibilitäten können verschiedene Laufzeitfehler auftreten. In solchen Fällen gibt es keine spezifische Ausnahme. Die Art und Weise, wie der Fehler zur Laufzeit gemeldet wird, hängt von der Art der Codeänderung ab, die das Problem verursacht hat.
Diese Fehler sollten in Ihrem endgültigen Produktionscode nicht auftreten, solange die gesamte Anwendung für die veröffentlichte Version Ihres Produkts neu erstellt wird. Assemblys, die für die Öffentlichkeit freigegeben werden, sollten mit einer offiziellen Versionsnummer gekennzeichnet werden, wodurch sichergestellt wird, dass diese Probleme vermieden werden. Weitere Informationen finden Sie unter Assembly-Versionierung.
So diagnostizieren und beheben Sie einen Inkompatibilitätsfehler
Möglicherweise treten Laufzeitausnahmen oder andere Fehlerbedingungen im Code auf, der auf eine andere Assembly verweist. Wenn Sie keine andere Ursache identifizieren können, ist das Problem möglicherweise eine veraltete Assembly.
Isolieren und reproduzieren Sie zuerst die Ausnahme oder eine andere Fehlerbedingung. Ein Problem, das aufgrund einer veralteten Ausnahme auftritt, sollte reproduzierbar sein.
Überprüfen Sie den Zeitstempel aller Assemblys, auf die in Ihrer Anwendung verwiesen wird.
Wenn die Zeitstempel von referenzierten Assemblys später als der Zeitstempel der letzten Kompilierung Ihrer Anwendung sind, ist die Anwendung veraltet. Wenn sie nicht mehr aktuell ist, kompilieren Sie Ihre Anwendung mit den neuesten Assemblys, und bearbeiten Sie den Code bei Bedarf.
Führen Sie die Anwendung erneut aus, führen Sie die Schritte aus, die das Problem reproduzieren, und stellen Sie sicher, dass die Ausnahme nicht auftritt.
Beispiel
Das folgende Programm veranschaulicht das Problem: Es wird zunächst die Zugriffsebene einer Methode reduziert, und dann versucht, auf diese Methode in einer anderen Assembly zuzugreifen, ohne sie neu zu kompilieren. Zuerst kompilieren changeaccess.cpp . Es ist die referenzierte Assembly, die geändert wird. Kompilieren Sie dann referencing.cpp. Es sollte erfolgreich kompiliert werden. Reduzieren Sie als Nächstes den Zugriff der aufgerufenen Methode. Kompilieren Sie changeaccess.cpp neu mit der Compileroption /DCHANGE_ACCESS. Es macht die access_me-Methode protected, anstatt public, wodurch sie nicht von außerhalb Test oder seinen Ableitungen aufgerufen werden kann. Führen Sie die Anwendung erneut aus, ohne referencing.exe neu zu kompilieren. Ein MethodAccessException tritt auf.
// 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;
}
};
Dies ist die Quelle für die referenzierende Assembly:
// 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;
}
Siehe auch
.NET-Programmierung mit C++/CLI (Visual C++)
Interoperabilität mit anderen .NET-Sprachen (C++/CLI)
Verwaltete Typen (C++/CLI)
#using-Direktive