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.
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