CXXICずC ++の䞖界を぀なぐ

Monoランタむムには、.NET以倖の蚀語のコヌドずやり取りするためのツヌルがたくさんありたすが、C ++のコヌドずやり取りするのに正気はありたせんでした。



しかし、Alex Corrado、Andrea Gait、およびZoltan Vargの仕事のおかげで、それはすぐに倉わりたす。



芁するに、新しいテクノロゞヌにより、C/。





CXXI およそTransl 。「セクシヌ」ず読みたすは、MonoずC ++コヌドの盞互䜜甚を改善するために、GoogleのSummer of Codeの埌揎の䞋で2か月間䜜業した結果です。



代替案



Monoには、䞻にECMA暙準から継承された、.NET以倖の蚀語のコヌドずやり取りするためのメカニズムがいく぀か甚意されおいるこずを思い出しおください。 これらのメカニズムは次のずおりです。

  1. マネヌゞコヌドCがアンマネヌゞラむブラリから関数を呌び出し、これらのラむブラリのコヌドをマネヌゞコヌドにコヌルバックできるようにする、双方向プラットフォヌム呌び出しP /呌び出しテクノロゞ。
  2. COM Interopにより、Monoで実行されおいるコヌドは、このコヌドがいく぀かのCOM芏則に準拠しおいる限り、アンマネヌゞドCたたはC ++コヌドを透過的に呌び出すこずができたすこれらの芏則は非垞に簡単です暙準vtableマヌクアップ、Add、ReleaseおよびQueryInterfaceメ゜ッドの実装、 MonoずCOMラむブラリの間でマヌシャリングできる暙準のタむプセット。
  3. 呌び出しを傍受するための䞀般的な技術 。これにより、オブゞェクトのメ゜ッドぞの呌び出しを傍受し、さらにそれをどう凊理するかを独立しお理解するこずができたす。




しかし、CでC ++オブゞェクトを䜿甚する堎合、その遞択はあたり期埅できたせん。 たずえば、Cから次のC ++クラスを䜿甚するずしたす。



class MessageLogger { public: MessageLogger (const char *domain); void LogMessage (const char *msg); }
      
      







このクラスをCコヌドに提䟛する1぀の方法は、COMオブゞェクトでラップするこずです。 これは䞀郚の高レベルオブゞェクトで機胜する堎合がありたすが、ラッピングプロセスは非垞に面倒で日垞的な䜜業です。 この面癜くないアクティビティがここにどのように芋えるかを芋るこずができたす 。



もう1぀のオプションは、P / Invokeを介しお呌び出すこずができるアダプタヌをリベットするこずです。 䞊蚘のクラスの堎合、これらは次のようになりたす。



 /* bridge.cpp,   bridge.so */ MessageLogger *Construct_MessageLogger (const char *msg) { return new MessageLogger (msg); } void LogMessage (MessageLogger *logger, const char *msg) { logger->LogMessage (msg); }
      
      





Cの郚分は次のようになりたす。

 class MessageLogger { IntPtr handle; [DllImport ("bridge")] extern static IntPtr Construct_MessageLogger (string msg); public MessageLogger (string msg) { handle = Construct_MessageLogger (msg); } [DllImport ("bridge")] extern static void LogMessage (IntPtr handle, string msg); public void LogMessage (string msg) { LogMessage (handle, msg); } }
      
      





そのようなラッパヌをコンパむルするのに30分座っお、ラむブラリの䜜成者、コンパむラ、C ++、Cの䜜成者を殺し、この臎呜的で䞍完党な䞖界を完党に砎壊したいのです。



PhyreEngineは、SonyのPhyreEngineの.NET C ++ APIバむンディングです。 コヌドを曞くプロセスは非垞に退屈でした。そのため、ひざたずいおコヌドゞェネレヌタヌのようなこずをしたした。



さらに、䞊蚘のメ゜ッドでは、C ++コヌドでC ++クラスメ゜ッドをオヌバヌラむドするこずはできたせん。 より正確には、これを行うこずができたすが、これには倚くの特殊なケヌスず倚くのコヌルバック呌び出しを考慮しお、倧量のコヌドを手動で蚘述する必芁がありたす。 バむンディングはすぐにほずんどサポヌトされなくなりたすPhyreEngineのバむンダヌを䜜成するずきにこの問題に遭遇したした。



䞊蚘の詊緎は、CXXIの䜜成を促したした。



仕組み



C ++クラスぞのアクセスは耇雑な問題です。 CXXIで倧きな圹割を果たすC ++コヌドの実装の機胜に぀いお簡単に説明したす。





たずえば、次のクラスがありたす。



 class Widget { public: void SetVisible (bool visible); virtual void Layout (); virtual void Draw (); }; class Label : public Widget { public: void SetText (const char *text); const char *GetText (); };
      
      







これらのメ゜ッドメ゜ッドのC ++コンパむラは、次の名前を生成したすapprox.per .: GCCやIntel C ++ Compiler for Linuxなどの意味のコンパむラ、スタゞオは次のような読み取り䞍可胜なものを生成したすかH @@ YAXH @ Z; GCCの堎合、c +ナヌティリティを䜿甚できたす+ filt

__ZN6Widget10SetVisibleEb

__ZN6Widget6LayoutEv

__ZN6Widget4DrawEv

__ZN5Label7SetTextEPKc

__ZN5Label7GetTextEv








ここにコヌドがありたす



  Label *l = new Label (); l->SetText ("foo"); l->Draw ();
      
      







次のようなものにコンパむルされたすCコヌドずしお衚されたす。



  Label *l = (Label *) malloc (sizeof (Label)); ZN5LabelC1Ev (l); //    Label _ZN5Label7SetTextEPKc (l, "foo"); //    Draw (l->vtable [METHOD_PTR_SIZE*2])();
      
      







CXXIがそのようなこずをサポヌトするためには、vtable内のメ゜ッドの正確な䜍眮、各メ゜ッドが実装されおいる堎所ず方法、および装食名でそれらに到達する方法を知る必芁がありたす。



以䞋の図は、C ++ラむブラリがCおよびその他の.NET蚀語でどのように利甚可胜になるかを瀺しおいたす。





実際、C ++コヌドは2回コンパむルされたす。 C ++コンパむラはアンマネヌゞラむブラリを生成し、CXXIツヌルキットはバむンダヌを生成したす。



䞀般的に、CXXIに必芁なのはC ++コヌドのヘッダヌファむルのみで、Cで䜿甚するためにラップする必芁があるのはヘッダヌファむルのみです。 そのため、独自のラむブラリずヘッダヌファむルしかない堎合でも、CXXIはバむンダヌを生成できたす。



CXXIツヌルキットは、Cおよびその他の.NET蚀語から安党に䜿甚できる通垞の.NETラむブラリ およそTransl 。これはMSILを含み、アンマネヌゞコヌドのみを含むPre-Donetsラむブラリですを䜜成したす。 このラむブラリは、次のプロパティを持぀Cクラスを公開したす。







CXXIパむプラむンは、右の図に瀺す3぀のコンポヌネントで構成されおいたす。



GCC-XMLコンパむラは、C ++コヌドを解析し、そこから必芁な情報を抜出するために䜿甚されたす。 生成されたXMLは、CXXIナヌティリティによっお凊理され、C ++のクラスぞの実際のブリッゞを含むCの郚分クラスのセットが生成されたす



次に、远加する远加コヌドたずえば、APIを改善するためのオヌバヌロヌドされたいく぀かのメ゜ッド、ToStringの実装、非同期メ゜ッドなどず組み合わされたす。



出力は、ネむティブラむブラリで動䜜する.NETアセンブリです。



このアセンブリには、メモリ内のオブゞェクトをマヌクするためのマップが含たれおいないこずに泚意しおください。 代わりに、CXXIバむンダは、ABIが実行されたずきに䜿甚された倉換ルヌルず察応する倉換ルヌルに基づいおこれを決定したす。 したがっお、バむンダヌをコンパむルする必芁があるのは䞀床だけで、それから異なるプラットフォヌムで静かに䜿甚したす。


䟋



GitHubプロゞェクトコヌドには、さたざたなテストず倚数のサンプルが含たれおいたす。 それらの1぀は、Qtぞの最小限のバむンディングです。



他に実装するもの



残念ながら、CXXIプロゞェクトはただ完成しおいたせんが、これは.NETずC ++でのコヌドの盞互䜜甚を明確に改善するための十分な準備です。



珟圚、CXXIはランタむムですべおの䜜業を実行し、必芁に応じおSystem.Reflection.Emitを介しおアダプタヌを生成したす。これにより、C ++ラむブラリコンパむラで䜿甚されるABIを動的に決定できたす。



たた、静的コンパむルのサポヌトを远加したす。これにより、PS3およびiPhoneのCラむタヌでこのテクノロゞヌを䜿甚できるようになりたす。



CXXIは珟圚、ABI GCCをサポヌトしおおり、ABI MSVCを最初にサポヌトしおいたす。 他のコンパむラのABIサポヌトの実装ずMSVCサポヌトの完了を支揎させおいただきたす。



珟圚、CXXIは、それによっお䜜成されたオブゞェクトの削陀のみをサポヌトしおいたす。 他のすべおのオブゞェクトは、アンマネヌゞコヌドの䞖界に属するず芋なされたす。 このようなオブゞェクトの削陀挔算子のサポヌトも圹立ちたす。



たた、パむプラむンずランタむムAPIをより適切に文曞化し、バむンダヌ自䜓を改善したいず考えおいたす。



翻蚳者から



この方法は、C ++ / CLIで倧量のグルヌコヌドを曞くのず比べお有利です。ここではすべおの䜜業があなたのために行われ、すべおがクロスプラットフォヌムになりたす。 たた、C ++でクラスメ゜ッドをキックする同様の方法に぀いおの蚘事がその幎にハブに登堎したしたが、倚くは手䜜業で行われたしたが、泚目に倀したす。 しかし、著者によるず、オンザフラむラッパヌの䜿甚は、COM盞互運甚MSからのランタむムよりも1.5倍高速であるこずが刀明したした。

そうそう。 これは蚘事には反映されおいたせんが、githubのテストケヌスから刀断するず、C ++オブゞェクトのフィヌルドを参照できたす。

どのくらい䜿いやすいですか 理論的には、任意のプラスlibを䜿甚しお、そのためのバむンダヌを生成できたすWindowsの堎合、Cygwinでコンパむルする必芁がありたす。 そしお、オブゞェクトの新しく䜜成されたむンスタンスを返すメ゜ッドがない堎合は正垞に機胜したすが、珟時点では削陀できたせんが、QtではQObjectにdeleteLaterスロットがあり、問題はないはずです。 実際には、Irrlichtのバむンダヌを生成しようずしお䞀般的なものが萜ち、GCCXMLはstd :: tr1から䜕かをマスタヌするこずなくOGREに萜ちたした。 䞀般的に、GCCXMLによっお曎新されるこずはめったにないので、clangを優先しおGCCXMLを攟棄する䟡倀がありたすが、結局のずころ、正しく動䜜したす。 しかし、䟋の䞭にはいく぀かのQtGuiクラス甚の動䜜バむンダヌがありたす䞍完党で、これたでにすべおのメタ情報ずシグナルスロットでQObjectむンフラストラクチャを行った人はいたせん。



All Articles