Share via


Gewusst wie: Migrieren zu /clr

In diesem Artikel werden Probleme erläutert, die beim Kompilieren von systemeigenem Code mit /clr. (Weitere Informationen finden Sie unter /clr (Common Language Runtime Compilation).) /clr ermöglicht systemeigenen C++-Code das Aufrufen und Aufrufen von .NET-Assemblys zusätzlich zu anderen systemeigenen C++-Code. Weitere Informationen zu den Vorteilen der Kompilierung mit /clr, finden Sie unter Gemischte Assemblys (native und verwaltete Assemblys ) und native und .NET-Interoperabilität.

Bekannte Probleme beim Kompilieren von Bibliotheksprojekten mit /clr

Visual Studio enthält einige bekannte Probleme beim Kompilieren von Bibliotheksprojekten mit /clr:

  • Ihr Code kann zur Laufzeit Abfragetypen mit CRuntimeClass::FromName. Wenn sich ein Typ jedoch in einer MSIL-DLL befindet (kompiliert mit /clr), schlägt der Aufruf FromName möglicherweise fehl, wenn er auftritt, bevor die statischen Konstruktoren in der verwalteten DLL ausgeführt werden. (Dieses Problem wird nicht angezeigt, wenn der FromName Aufruf auftritt, nachdem Code in der verwalteten DLL ausgeführt wurde.) Um dieses Problem zu umgehen, können Sie die Erstellung des verwalteten statischen Konstruktors erzwingen: Definieren Sie eine Funktion in der verwalteten DLL, exportieren Sie es, und rufen Sie sie aus der nativen MFC-Anwendung auf. Beispiel:

    // MFC extension DLL Header file:
    __declspec( dllexport ) void EnsureManagedInitialization () {
       // managed code that won't be optimized away
       System::GC::KeepAlive(System::Int32::MaxValue);
    }
    

Kompilieren mit Visual C++

Bevor Sie es für jedes Modul in Ihrem Projekt verwenden /clr , kompilieren und verknüpfen Sie zuerst Ihr systemeigenes Projekt mit Visual Studio.

Die folgenden Schritte, die in der Reihenfolge befolgt wurden, stellen den einfachsten Pfad zu einer /clr Kompilierung bereit. Es ist wichtig, ihr Projekt nach jedem dieser Schritte zu kompilieren und auszuführen.

Upgrade von früheren Versionen von Visual Studio

Wenn Sie Visual Studio von einer früheren Version aktualisieren, werden möglicherweise Compilerfehler im Zusammenhang mit der erweiterten Standard-C++-Konformität in Visual Studio angezeigt.

Projekte, die mit früheren Versionen von Visual Studio erstellt wurden, sollten auch zuerst ohne /clrkompiliert werden. Visual Studio hat jetzt die C++-Standardkonformität und einige bahnbrechende Änderungen erhöht. Die Änderungen, die wahrscheinlich die größte Aufmerksamkeit erfordern, sind Sicherheitsfeatures im CRT. Code, der das CRT verwendet, erzeugt wahrscheinlich Veraltete Warnungen. Diese Warnungen können unterdrückt werden, aber die Migration zu den neuen sicherheitsunterstätigten Versionen von CRT-Funktionen wird bevorzugt, da sie eine bessere Sicherheit bieten und Sicherheitsprobleme in Ihrem Code aufdecken können.

Aktualisieren von Managed Extensions für C++

In Visual Studio 2005 und höheren Versionen wird Code, der mit verwalteten Erweiterungen für C++ geschrieben wurde, nicht kompiliert unter /clr.

Konvertieren von C-Code in C++

Obwohl Visual Studio C-Dateien kompiliert, müssen sie für eine /clr Kompilierung in C++ konvertiert werden. Der tatsächliche Dateiname muss nicht geändert werden. Sie können verwenden /Tp (siehe /Tc, , /Tp, /TC, /TP (Quelldateityp angeben).) Obwohl C++-Quellcodedateien erforderlich /clrsind, ist es nicht erforderlich, Ihren Code so umzugestalten, dass objektorientierte Paradigmen verwendet werden.

C-Code erfordert wahrscheinlich Änderungen, wenn er als C++-Datei kompiliert wird. Da die C++-Typsicherheitsregeln streng sind, müssen Typkonvertierungen explizit durch Umwandlungen vorgenommen werden. Beispielsweise gibt malloc einen void-Zeiger zurück, kann aber durch Umwandlung einem Zeiger zugewiesen werden, der auf einen beliebigen Typ in C zeigt:

int* a = malloc(sizeof(int));   // C code
int* b = (int*)malloc(sizeof(int));   // C++ equivalent

Auch Funktionszeiger sind in C++ streng typsicher, deshalb muss der folgende C-Code geändert werden. In C++ empfiehlt es sich, einen typedef Wert zu erstellen, der den Funktionszeigertyp definiert, und dann diesen Typ zum Umwandeln von Funktionszeigern verwenden:

NewFunc1 = GetProcAddress( hLib, "Func1" );   // C code
typedef int(*MYPROC)(int);   // C++ equivalent
NewFunc2 = (MYPROC)GetProcAddress( hLib, "Func2" );

C++ verlangt außerdem, dass Funktionen entweder einen Prototyp haben oder vollständig definiert sind, bevor auf sie verwiesen wird oder sie aufgerufen werden können.

Bezeichner, die in C-Code verwendet werden, die vorkommen, dass es sich um Schlüsselwort (keyword) in C++ (zvirtual. B. , , new, delete, booltrue, falseusw.) handeln muss, müssen umbenannt werden. Diese Änderung kann in der Regel mit einfachen Such- und Ersetzungsvorgängen erfolgen.

COMObj1->lpVtbl->Method(COMObj, args);  // C code
COMObj2->Method(args);  // C++ equivalent

Konfigurieren von Projekteinstellungen neu

Nachdem Das Projekt in Visual Studio kompiliert und ausgeführt wurde, sollten Sie neue Projektkonfigurationen erstellen /clr , anstatt die Standardkonfigurationen zu ändern. /clr ist mit einigen Compileroptionen nicht kompatibel. Durch das Erstellen separater Konfigurationen können Sie Ihr Projekt als systemeigene oder verwaltete Projekte erstellen. Wenn /clr im Dialogfeld eigenschaftenseiten ausgewählt ist, sind projekteinstellungen, die nicht kompatibel sind /clr , deaktiviert. (Deaktivierte Optionen werden nicht automatisch wiederhergestellt, wenn /clr sie später nicht ausgewählt sind.)

Erstellen neuer Projektkonfigurationen

Sie können die Option "Kopieren Einstellungen Von" im Dialogfeld "Neue Projektkonfiguration erstellen" (Erstellen>von Configuration Manager>Active Solution Configuration>New) verwenden, um eine Projektkonfiguration basierend auf ihren vorhandenen Projekteinstellungen zu erstellen. Erstellen Sie einmal eine Kopie Ihrer Konfiguration für die Debugkonfiguration und einmal für die Releasekonfiguration. Nachfolgende Änderungen können dann nur auf die /clr-spezifischen Konfigurationen angewendet werden, sodass die ursprünglichen Projektkonfigurationen erhalten bleiben.

Projekte, die benutzerdefinierte Buildregeln verwenden, erfordern möglicherweise zusätzliche Aufmerksamkeit.

Dieser Schritt hat auf Projekte, die Makefiles verwenden, unterschiedliche Auswirkungen. In diesem Fall kann ein separates Buildziel konfiguriert werden, oder eine für die Kompilierung spezifische /clr Version kann aus einer Kopie des Originals erstellt werden.

Ändern von Projekteinstellungen

/clr kann in der Entwicklungsumgebung ausgewählt werden, indem sie den Anweisungen in /clr (Common Language Runtime Compilation) folgen. Wie bereits erwähnt, werden in diesem Schritt automatisch sich widersprechende Projekteinstellungen deaktiviert.

Hinweis

Beim Upgrade eines verwalteten Bibliotheks- oder Webdienstprojekts von Visual Studio 2003 wird der Befehlszeileneigenschaftsseite die /ZlCompileroption hinzugefügt. Dies verursacht LNK2001 Fehler. Entfernen Sie /Zl die Befehlszeilen-Eigenschaftenseite , um die Fehler zu beheben. Weitere Informationen finden Sie unter /Zl (Standardbibliotheksname weglassen) und Festlegen von Compiler- und Buildeigenschaften.

Für Projekte, die mit Makefiles erstellt wurden, müssen inkompatible Compileroptionen manuell deaktiviert werden, sobald /clr sie hinzugefügt wurden. Informationen zu Compileroptionen, die nicht kompatibel sind /clr, finden Sie unter /clr Einschränkungen.

Vorkompilierte Kopfzeilen

Vorkompilierte Header werden unter /clr. Wenn Sie jedoch nur einige Ihrer CPP-Dateien /clr kompilieren (Kompilieren des Rests als systemeigene Datei), sind einige Änderungen erforderlich. Vorkompilierte Header, die mit /clr generiert werden, sind nicht mit vorkompilierten Headern kompatibel, die ohne /clrgeneriert werden, da /clr Metadaten generiert und benötigt werden. Kompilierte /clr Module können keine vorkompilierten Header verwenden, die keine Metadaten enthalten, und nicht-Module/clr können keine vorkompilierten Headerdateien verwenden, die Metadaten enthalten.

Die einfachste Möglichkeit zum Kompilieren eines Projekts, in /clr dem einige Module kompiliert werden, besteht darin, vorkompilierte Header vollständig zu deaktivieren. (Öffnen Sie im Dialogfeld "Eigenschaftenseiten" des Projekts das C/C++ -Knoten, und wählen Sie "Vorkompilierte Header" aus. Ändern Sie dann die Eigenschaft "Vorkompilierte Kopfzeilen erstellen/verwenden" in "Keine vorkompilierten Header".)

Insbesondere bei großen Projekten bieten vorkompilierte Header jedoch eine wesentlich bessere Kompilierungsgeschwindigkeit, sodass das Deaktivieren dieses Features nicht wünschenswert ist. In diesem Fall empfiehlt es sich, die /clr und nicht-Dateien/clr so zu konfigurieren, dass separate vorkompilierte Header verwendet werden. Sie können sie in einem Schritt konfigurieren: Multi-select the modules to compile with /clr by using Projektmappen-Explorer. Klicken Sie mit der rechten Maustaste auf die Gruppe, und wählen Sie "Eigenschaften" aus. Ändern Sie dann sowohl die Eigenschaften "PCH Through File" als auch "Precompiled Header File", um einen anderen Headerdateinamen bzw. eine PCH-Datei zu verwenden.

Beheben von Fehlern

Das Kompilieren des Codes mit /clr kann zu Compiler-, Linker- oder Laufzeitfehlern führen. In diesem Abschnitt werden die häufigsten Probleme behandelt.

Metadatenzusammenführung

Unterschiedliche Datentypversionen können den Linker scheitern lassen, weil die für die beiden Typen generierten Metadaten nicht übereinstimmen. (Fehler treten auf, wenn Sie Elemente eines Typs bedingt definieren, aber die Bedingungen sind nicht für alle CPP-Dateien identisch, die den Typ verwenden.) In diesem Fall schlägt der Linker fehl, und meldet nur den Symbolnamen und den Namen der zweiten OBJ-Datei, in der der Typ definiert wurde. Möglicherweise ist es hilfreich, die Reihenfolge zu drehen, in der OBJ-Dateien an den Linker gesendet werden, um den Speicherort der anderen Version des Datentyps zu ermitteln.

Ladeprogramm-Deadlock

Das "Loader Lock Deadlock" kann auftreten, ist aber deterministisch und wird zur Laufzeit erkannt und gemeldet. Ausführliche Informationen zu Hintergrund, Anleitungen und Lösungen finden Sie unter Initialisierung gemischter Assemblys .

Datenexporte

Das Exportieren von DLL-Daten ist fehleranfällig und wird im /clr Code nicht empfohlen. Der Grund dafür ist, dass die Initialisierung des Datenabschnitts einer DLL erst garantiert wird, wenn ein verwalteter Teil der DLL ausgeführt wird. Referenzmetadaten mit #using Direktiven.

Typsichtbarkeit

Native Typen sind private standardmäßig. Ein private systemeigener Typ ist außerhalb der DLL nicht sichtbar. Beheben Sie diesen Fehler, indem Sie zu diesen Typen public hinzufügen.

Gleitkomma- und Ausrichtungsprobleme

__controlfp wird in der Common Language Runtime nicht unterstützt. (Weitere Informationen finden Sie unter _control87, , __control87_2_controlfp.) Die CLR respektiert alignauch nicht .

COM-Initialisierung

Die Common Language Runtime initialisiert COM automatisch, wenn ein Modul initialisiert wird (wenn COM automatisch als MTA initialisiert wird). Folglich führt explizites Initialisieren von COM zu Rückgabecodes, die angeben, dass COM bereits initialisiert ist. Wenn Sie versuchen, COM mit einem bestimmten Threadingmodell zu initialisieren, obwohl die CLR COM bereits mit einem anderen Threadingmodell initialisiert hat, kann die Anwendung möglicherweise nicht ausgeführt werden.

Die Common Language Runtime startet COM standardmäßig als MTA; verwenden /CLRTHREADATTRIBUTE (CLR-Thread-Attribut festlegen), um das COM-Modell zu ändern.

Leistungsprobleme

Möglicherweise wird die Leistung verringert, wenn systemeigene C++-Methoden, die mit MSIL generiert werden, indirekt aufgerufen werden (über virtuelle Funktionsaufrufe oder mithilfe von Funktionszeigern). Weitere Informationen finden Sie unter Double Thunking.

Wenn Sie von systemeigenem zu MSIL wechseln, werden Sie feststellen, dass sich die Größe Ihres Arbeitssatzes erhöht. Diese Erhöhung geschieht, da die Common Language Runtime viele Features bereitstellt, um sicherzustellen, dass Programme ordnungsgemäß ausgeführt werden. Wenn Ihre /clr Anwendung nicht ordnungsgemäß ausgeführt wird, sollten Sie die standardmäßige Compilerwarnung (Stufe 1 und 3) C4793 aktivieren.

Programmabstürzen beim Herunterfahren

In einigen Fällen kann die CLR heruntergefahren werden, bevor der verwaltete Code ausgeführt wird. Verwendung von std::set_terminate und SIGTERM kann das Herunterfahren verursachen. Weitere Informationen finden Sie unter signal Konstanten und set_terminate.

Verwenden neuer Visual C++-Features

Nachdem Ihre Anwendung kompiliert, links und ausgeführt wurde, können Sie mit der Verwendung von .NET-Features in jedem Modul beginnen, das mit /clrkompiliert wurde. Weitere Informationen finden Sie unter Component Extensions for Runtime Platforms.

Weitere Informationen zur .NET-Programmierung in Visual C++ finden Sie unter:

Siehe auch

Gemischte (native und verwaltete) Assemblys