2017-02-26 5 views
4

Ich habe ein Problem zu verstehen, wie verwaltetes C++ funktioniert und kompiliert.Verstehen von verwaltetem C++

In .NET Framework können Sie Code in C#/VB/F #/etc entwickeln. und alle diese Sprachen werden in derselben Common Intermediate Language (CIL) kompiliert, die Java Bytecode ähnlich ist. Theoretisch kann die CIL auf jeder Plattform montiert werden (Mono hat es praktisch gemacht). Unter Windows kompiliert CLR die CIL in nativen Code Just-In-Time (JIT) und alles läuft reibungslos und gut zu gehen.

Wie wird Managed C++ jetzt kompiliert? Kompiliert es in CIL-Code und wartet, bis CLR es mit JIT ausführt? Ich denke nicht, denn Managed C++ kann Standard-C++ - Code verwenden (der nicht nach CIL kompiliert wird). Außerdem, wie kann es .NET-Assemblies (CIL) verwenden?

Ich würde jede Hilfe zu schätzen wissen. Dank

EDIT:

ich diesen answer gesehen haben. Es stellt fest, dass der verwaltete Code in C++/CLI nach MSIL kompiliert wird und Sie den nicht verwalteten Code entweder in systemeigenem Code oder in MSIL kompilieren können. Daher verstehe ich jetzt, wie der Aufruf von .NET-Assemblies möglich ist.

Wie auch immer, ich verstehe immer noch nicht, wie der nicht verwaltete C++ - Code mit dem verwalteten Code in derselben Assembly ausgeführt werden kann, wenn der nicht verwaltete Code in nativen Code kompiliert wurde. Irgendwelche Ideen?

Antwort

6

Es ist ein großes Thema mit sehr detaillierten Implementierungsdetails. Es ist schwer, sie alle anzusprechen, aber in der Frage gibt es einige Missverständnisse. Lasst uns diese ansprechen, könnte helfen, zur nächsten Stufe zu kommen.

Darüber hinaus, wie kann es .NET-Assemblys (CIL) verwenden?

Nicht nur CIL, erzeugt der Linker eine Mixed-Mode- Montage. Enthält beide .NET-Metadaten + MSIL und nativen Code. Soweit es den OS-Loader betrifft, ist der native Code in der ausführbaren Datei normal. Nicht anders als bei einem nativen C++ - Compiler. Es wird wie ein reines natives ausführbares Bild geladen und verschoben. Es ist die .NET-Metadaten + MSIL, die der Sonderling ist. Für den Loader sieht es nur aus wie ein Stück Daten, es berührt es überhaupt nicht. Nur die CLR tut es.

... verwenden Standard C++ Code (die nicht zu CIL kompiliert wird)

Nicht ganz genau, native C++ Code kompiliert werden kann oder Maschinencode MSIL. Was Sie erhalten, hängt davon ab, ob die/clr-Kompilieroption verwendet wurde oder die # pragma-Verwaltung, die auf der Funktionsebene wirksam war. CIL vergleicht das nicht gut mit dem Bytecode, der in der Java JVM verwendet wird. Es ist leistungsfähiger und kann jeden C++ 03-konformen nativen C++ - Code unterstützen. Manchmal tun Sie dies absichtlich, um einen umgekehrten Pin-Voicemail (nativen Code, der verwalteten Code aufruft) zu nutzen.Manchmal wird es versehentlich ausgeführt und zu viel nativer C++ - Code wird in MSIL kompiliert. Der Maschinencode, der durch den Jitter erzeugt wird, ist nicht so optimal (er optimiert unter Zeitbeschränkungen) und wird in keiner Weise verwaltet. Es ist nicht verifizierbar und bekommt keine Müllsammlerliebe.

Das beste mentale Image für CIL ist die Zwischenrepräsentation, die in jedem nativen C++ - Compiler zwischen dem Front-End (Parser) und dem Back-End (Code-Generator und Optimierer) verwendet wird. Oft wird ein unsichtbares Implementierungsdetail sichtbar, wenn Sie einen C++ - Compiler verwenden, der LLVM verwendet (wie Clang). Der .NET-Just-in-Time-Compiler führt zur Laufzeit zur Laufzeit das aus, was LLVM tut.


Die meisten Programmierer haben die mentale Bild eines riesigen Modusschalter ausgelöst wird, wenn verwalteten Code nativen Code aufruft (oder umgekehrt). Das ist überhaupt nicht richtig. Vielleicht möchten Sie einen Blick auf this post werfen, zeigt den Unterschied zwischen Maschinencode vom C++ Compiler-Back-End und dem Jitter erzeugt. Entscheidend ist, dass es fast identisch ist, ein wesentliches Merkmal, um sicherzustellen, dass verwalteter Code mit nativem Code konkurrieren kann. Hilft zu verdeutlichen, wie verwalteter Code, der systemeigenen Code aufruft, oder umgekehrt, nicht besonders ist.

Ein weiteres Missverständnis ist, dass verwalteter Code automatisch sicherer ist. Nicht ganz richtig, eine Sprache wie C# lässt Sie mit Zeigern herumkritzeln und auf dem Stack herumkritzeln, so wie Sie es mit C++ tun können, und Sie können den Speicher genauso leicht beschädigen. Es ist nur besser partitioniert, es zwingt Sie, mit dem Schlüsselwort unsafe explizit darüber zu sein. Keine solchen Einschränkungen für C++/CLI, nichts geht.

Der wesentliche Unterschied zwischen verwaltetem und nativem Code ist eine Datenstruktur, die der Jitter generiert, wenn er MSIL kompiliert. Zusätzliche Daten, die Sie nicht von einem nativen Compiler erhalten. Diese Daten werden vom Garbage Collector benötigt und geben Auskunft darüber, wie man die Objektstämme zurück findet. Mehr über diese Daten in this post. Sich an diese Daten anpassen zu müssen und dem GC zu erlauben, seine Arbeit zu erledigen, macht den verwalteten Code zur Laufzeit etwas langsamer.

+0

Große Antwort. Besonders das: "CIL vergleicht das nicht gut mit dem Bytecode, der in der Java JVM verwendet wird. Es ist leistungsfähiger und kann jeden C++ 03-konformen nativen C++ - Code unterstützen." Als ich einen Java-Job bekam, schaute ich auf ihre Bytecode-Spezifikation und weinte! – hoodaticus

0

Mangled C++ ist veraltet. Um nativen C++ - und Manged-Code zu schreiben, müssen Sie heute C++ \ CLI verwenden. Es entspricht CLR und kann andere .net-Assemblies ausführen. Sie können auch einen nativen Aufruf verwenden, diese sind für interoperabilitybetween nativen Code und .NET-Code .NET Assembly Verweis auf diese Assembly in Ihrem Projekt hinzufügen aufrufen und in Ihrem Code hinzufügen:

using namespace System; 
+1

Ich schätze den Hinweis über die C++/CLI. Sie können den nicht verwalteten Teil von C++/CLI jedoch weiterhin in systemeigenen Code (nicht MSIL) kompilieren. Wie funktioniert das, da der verwaltete Teil des Codes gezwungen wird, nach MSIL zu kompilieren? – Everyone

+1

@ Everyone, das Dateiformat ist immer noch eine PE-Datei und kann nativen Code wie jeder andere enthalten (auf Kosten der Cross-Portabilität). Die Anweisung [calli] (https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.calli (v = vs.110) .aspx) kann verwendet werden, um die native Methode aufzurufen . –

+0

Wenn Sie die C++/CLI nicht in nativ (nur) kompilieren können. Wenn Sie Anrufe für verwalteten Code haben –

Verwandte Themen