2017-02-26 3 views
4

Je n'arrive pas à comprendre comment le C++ géré fonctionne et se compile.Présentation de C++ managé

Dans .NET Framework, vous pouvez développer du code en C#/VB/F #/.. etc. et tous ces langages seront compilés au même langage intermédiaire commun (CIL) qui est similaire au Java Bytecode. Théoriquement, le CIL peut être monté sur n'importe quelle plateforme (Mono l'a rendu pratique). Sous Windows, CLR compile le CIL en code JIT (Just-In-Time) natif et tout se passe bien et est parfait.

Maintenant, comment le C++ géré est-il compilé? Est-ce qu'il compile au code CIL et attend que CLR l'exécute en utilisant JIT? Je ne pense pas, parce que Managed C++ peut utiliser le code standard C++ (qui n'est pas compilé en CIL). De plus, comment peut-il utiliser les assemblages .NET (qui sont CIL)?

J'apprécierais toute aide. Merci

EDIT:

Je l'ai vu answer. Il note que dans C++/CLI, le code managé est compilé à MSIL, et vous avez une option pour compiler le code non managé soit au code natif ou à MSIL. Par conséquent, je comprends maintenant comment l'appel aux assemblages .NET est possible. Quoi qu'il en soit, je ne comprends toujours pas comment le code non géré C++ peut s'exécuter avec le code managé dans le même assembly si le code non managé a été compilé en code natif. Des idées?

Répondre

6

Il est un grand sujet avec des détails de mise en œuvre très graveleux. Difficile de tous les aborder, mais il y a quelques idées fausses dans la question. Adressons-nous à ceux qui pourraient vous aider à passer à l'étape suivante.

De plus, comment peut-il utiliser des assemblages .NET (qui sont CIL)?

Non seulement CIL, l'éditeur de liens produit un ensemble en mode mixte. Contient à la fois les métadonnées .NET + msil et code natif. En fait, en ce qui concerne le chargeur de système d'exploitation, c'est le code natif dans le fichier exécutable qui est normal. Pas différent du type produit par un compilateur C++ natif. Il est chargé et déplacé juste comme une image exécutable native pure. C'est la méta-donnée .NET + msil qui est l'oddball. Pour le chargeur, cela ressemble à un morceau de données, il ne le touche pas du tout. Seul le CLR le fait.

... Utilisez le code C++ standard (non compilé à CIL)

Pas tout à fait précis, le code C++ natif peut être compilé pour MSIL ou code machine. Ce que vous obtenez dépend de l'utilisation de l'option/clr compile ou du #pragma géré au niveau de la fonction. CIL ne compare pas très bien, disons, le bytecode utilisé dans la JVM Java. Il est plus puissant et peut prendre en charge tout code C++ natif compatible C++ 03. Parfois, vous le faites exprès pour profiter du reverse pinvoke (code managé d'appel de code natif).Parfois, cela se fait par accident et le code C++ natif est entièrement compilé en msil. Le code machine produit par la gigue n'est pas optimal (il optimise en fonction des contraintes de temps) et n'est géré en aucune façon. Il n'est pas vérifiable et n'obtient pas l'amour du garbage collector.

La meilleure image mentale de CIL est la représentation intermédiaire utilisée dans tout compilateur C++ natif entre le frontal (parseur) et le back-end (générateur de code et optimiseur). Souvent un détail d'implémentation invisible mais devient plus visible lorsque vous utilisez un compilateur C++ qui utilise LLVM (comme le fait Clang). Le compilateur juste-à-temps .NET fait au moment de l'exécution ce que fait LLVM au moment de la compilation.


La plupart des programmeurs ont l'image mentale d'un commutateur de mode géant étant lancé lorsque le code managé appelle le code natif (ou l'inverse). Ce n'est pas exact du tout. Vous pouvez jeter un oeil à this post, montre la différence entre le code machine produit par le back-end du compilateur C++ et la gigue. La clé est presque identique, une caractéristique essentielle pour s'assurer que le code managé est compétitif avec le code natif. Aide à clarifier comment le code géré appelant le code natif, ou l'inverse, n'est pas si spécial.

Une autre idée fausse est que le code managé est automatiquement plus sûr. Pas tout à fait vrai, un langage comme C# vous permet de faire la fête avec des pointeurs et de gribouiller sur la pile comme vous le pouvez avec C++ et vous pouvez corrompre la mémoire aussi facilement. Il est juste mieux partitionné, il vous oblige à être explicite à ce sujet avec le mot-clé unsafe. Pas de telles contraintes sur C++/CLI, tout est permis.

La différence essentielle entre le code géré et le code natif est une structure de données que la gigue génère lorsqu'elle compile msil. Données supplémentaires que vous ne recevez pas d'un compilateur natif. Cette donnée est requise par le garbage collector, elle lui indique comment retrouver les racines des objets. Plus d'informations sur ces données dans this post. Devoir se conformer à ces données et permettre au GC de faire son travail est ce qui rend le code managé un peu plus lent à l'exécution. J'apprécie la note à propos de la C++/CLI

+0

Bonne réponse. En particulier: "CIL ne se compare pas très bien à, disons, le bytecode utilisé dans la JVM Java, il est plus puissant et peut supporter n'importe quel code C++ natif compatible C++ 03". Quand j'ai eu un travail Java, j'ai regardé leurs spécifications bytecode et j'ai pleuré! – hoodaticus

0

Manged C++ est déprécié. Aujourd'hui, pour écrire du code C++ et Manged natif, vous devez utiliser C++ \ CLI. Il est conforme à CLR et il peut exécuter d'autres assemblages .net. Vous pouvez également utiliser l'appel natif, ce sont grands pour interoperabilitybetween code natif et le code .NET Pour appeler .NET Assembly ajouter une référence dans votre projet à cette Assemblée et ajouter dans votre code:

using namespace System; 
+1

Cependant, vous pouvez toujours compiler la partie non gérée de C++/CLI en code natif (non MSIL). Alors, comment cela fonctionne-t-il puisque la partie managée du code sera obligée de compiler vers MSIL? – Everyone

+1

@Tout le monde, le format de fichier est toujours un fichier PE et peut contenir du code natif comme un autre (au prix de la portabilité croisée). L'instruction [calli] (https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.calli (v = vs.110) .aspx) peut être utilisée pour appeler la méthode native . –

+0

Si vous ne pouvez pas compiler le C++/CLI en natif (seulement). Si vous avez des appels pour le code managé –