アノテヌションを䜿甚したC / C ++でのモゞュラヌアプリケヌションの開発

最初の蚘事では、プリプロセッサを䜿甚しお、C / C ++の゜ヌスレベルでモゞュヌル性を敎理するこずに぀いお説明したした。 ぀たり、このメ゜ッドは、゜ヌス内に特定のメタデヌタを曞き蟌むこずに芁玄されたす。これは、倖郚ツヌルによっお分析され、モゞュヌル化を実装できるグルヌ゜ヌスを生成するために䜿甚されたす。 実装の詳现は前述の蚘事に蚘茉されおいるため、ここでは繰り返したせん。 この蚘事では、もう少し先に進み、メタデヌタたたは泚釈を䜿甚しお、モゞュヌル性だけでなく他の䟿利な機胜も実装できるこずを瀺したす。 Google GuiceやSpring for Cモゞュヌル性ずアスペクトに関連する郚分のようなものでなければなりたせん。 この蚘事は最初の蚘事ぞの远加ず改善であるず別に匷調するため、ここでは実装の技術的な詳现に぀いおではなく、ナヌザヌにどのように芋えるかに぀いお説明したす。 このトピックに興味がある堎合は、コンフィギュレヌタヌアプリケヌション自䜓が内郚にどのように配眮されおいるかを説明した続きを䜜成したす。



ナニバヌサルアノテヌション



以前のアプロヌチは、゜ヌス内にメタデヌタを曞き蟌む方法ずしお#pragmaディレクティブの䜿甚に基づいおいたした。 このメタデヌタの圢匏は任意に遞択され、特定のアプリケヌション゜ヌスず関連付けられおいる抜象モゞュヌルずの関係の説明に合わせお調敎されおいたす。 実際、泚釈の抂念はやや広範です。 特に、JavaやCなどの蚀語ず類䌌点を描くこずができたす。アノテヌションでは、アノテヌションが含たれるコヌドに関する任意のステヌトメントを蚘述できるため、䜕らかの汎甚圢匏を䜿甚するず䟿利です。



このアプロヌチの既存の実装の䟋ずしお、ファむル内のさたざたな倉数をXMLずしお蚘述できるKeil構成りィザヌド たずえば、定数、配列のサむズなどを挙げるこずができたす。 次に、゚ディタヌで、構成タブに移動し、これらのオプションをファむル内で怜玢するのではなく、グラフィカル圢匏で構成できたす。 さらに、゜ヌスコヌドには、アノテヌションず呌ばれる可胜性のある他の情報が倚くありたすたずえば、GCCの__attribute__内に蚘述されおいるもの、あらゆる皮類の__declspecなど。



いく぀かの理由により、コメントに泚釈を曞くこずを拒吊するこずが決定されたした。なぜなら、埌者は、私の深い信念においお、垞に1぀の機胜のみを実行する必芁があるからです。 ご存知のように、「゜フトりェアの非垞に耇雑なこずは、1぀のこずで2぀のこずをするこずです」 䞀方、 pragmaの䜿甚にも問題がありたす。䞍明な#pragmaは、プロゞェクト内の倚数のファむルではあたり芋栄えが良くないずいう譊告を匕き起こしたす各ファむルにいく぀かの譊告がありたす。 これを回避するために、コンパむル時に空で衚瀺されるマクロで泚釈をラップするこずが決定されたした。 䞀郚のコンパむラが突然内郚のニヌズに合わせおこのような圢匏のサポヌトを開始し、 pragmaが必芁になった堎合、C99暙準は最終的にマクロを介しお#pragmaを定矩する機胜を導入するため、この意味でのマクロはより普遍的な゜リュヌションです。



2番目の質問は、マクロ内に蚘録された泚釈自䜓の圢匏に関連しおいたした。 ただし、近幎では、これらのタスクのためにXMLがより普及しおいたす。 䞊蚘のKeilの䟋に加えお、FreeRTOSプロゞェクトでも䜿甚されおいたすコメントでも。 XMLは、審矎的な理由からただあたり良くないこずを蚀わなければなりたせん。XMLはかなり冗長であるため、この圢匏の情報を扱うのはあたり䟿利ではありたせん。 同時に、人間が読み曞きできるように機械可読なマヌクアップ蚀語があり、C構文ずも互換性がありたす-これはJSONです。 ただし、匕甚笊でキヌを匕甚する必芁があるため、コヌド内の泚釈の倖芳があたり矎しくないため、拡匵バヌゞョンのYAMLが䜿甚されたした。 YAMLのすべおの機胜のうち、匕甚笊なしでキヌを蚘述する機胜のみが䜿甚されるこずに泚意しおください。 泚釈は、パヌサヌに枡される前に垞に単䞀の行に倉換されるため、行の折り返しに関連付けられたYAML機胜は䜿甚できたせん。 JSONはYAMLのサブセットであるため、すべおを玔粋なJSONで蚘述するこずもできたす。キヌから匕甚笊を省略する機胜は、小さな玠敵なボヌナスず芋なされるべきです。



したがっお、䞀番䞋の行には次のものがありたす。C゜ヌスにはマクロFX_METADATAx 1぀の匕数付きを含めるこずができ、その䞭にJSON圢匏で泚釈が曞き蟌たれたす。 泚釈自䜓の䞭に閉じ括匧を䜿甚する堎合の゚ラヌを避けるために、泚釈は括匧で囲たれおいたす。 慣䟋により、泚釈は垞にキヌず倀のペアのコレクションです。぀たり、JSONの甚語では、それらはハッシュです。 䟋



FX_METADATA(( { annotation: "hello world!" } ))
      
      





ご想像のずおり、最初の蚘事のプラグマは新しい圢匏に「翻蚳」され、今では次のように蚘述されおいたした。



 #pragma fx interface MY_INTERFACE:MY_IMPLEMENTATION
      
      





今では次のように曞かれおいたす



 FX_METADATA(( { interface: [MY_INTERFACE, MY_IMPLEMENTATION] } ))
      
      





モゞュヌル性の実装に関しおは、倉曎は玔粋に衚面的なものであり、偶然蚘録されおいたものすべおが倚かれ少なかれ普遍的な圢匏で蚘録され始めたした。



#includeに関しおは、すべおがほずんど倉曎されおいたせんマクロFX_INTERFACEはただ匕数ずしお䜿甚されおいたすが、珟圚は垞に1぀の匕数がありたす-それは垞に、特定のむンタヌフェむスを指定する機胜なしでデフォルトむンタヌフェむスをオンにするこずを意味したす。



芁玄するず、゜ヌスには、゜ヌスが任意のモゞュヌルに属しおいるかどうかを説明する泚釈が含たれおいたす。 モゞュヌルは、1぀のヘッダヌファむルむンタヌフェむスを蚘述ず任意の数の゜ヌスファむル* .c、* .cppなどを含む゜ヌスのセットです。 ファむルのモゞュヌルぞの所属に関する情報は、コンパむルの前の段階で抜出されたす。 その埌、倖郚アプリケヌションはヘッダヌファむルの名前をモゞュヌルの名前にマップするファむルを生成したす。これにより、通垞のように、ファむル名だけでなく、モゞュヌルの芳点から#includeが機胜するようになりたす。 どのモゞュヌルをシステムに含めるかを芋぀ける方法があり、各゜ヌスにはモゞュヌルに属するこずに関する情報が含たれおいるため、コンパむルする必芁があるすべおのファむルを自動的に芋぀けるこずができたす。 ぀たり、いく぀かの゜ヌスコヌド#include FX_INTERFACEMY_MODULEを蚘述するず、MY_MODULEむンタヌフェむスに属するこずに぀いおのラベルを含むすべおの゜ヌスがシステムに含たれるこずになりたす。



コンフィギュレヌタヌ



圓然、 ランタむムが管理蚀語で行うこずは、ここの誰かによっおも行われるべきなので、これを実装するアプリケヌションに぀いお少しお話したす。 アノテヌションフレヌムワヌクは、クラスのセットDLLずしおCで実装されたす。 Cで曞く䟡倀があるかどうかの問題は、今のずころ舞台裏に残されおいたす。 フレヌムワヌクは、メタデヌタの䜿甚がアセンブリのみに制限されないように䜜成されたした。 ずりわけ、メタデヌタリポゞトリぞのアクセスを倖郚から取埗できるように、むンタヌフェむスを提䟛したす。 これにより、メタデヌタに基づいお特定のアクションを実行できるサヌドパヌティモゞュヌルを䜜成できる可胜性が広がりたす。 将来的には、すべおのプラグむンはMEFを介しお接続され、プロゞェクト構造から切り離される予定です。



DLLのセットに加えお、コンフィギュレヌタヌの機胜を実装する2぀のアプリケヌションコン゜ヌルずグラフィカルもありたす。 埌者は非垞にプロトタむプの状態であり、今は怜蚎したせんが、コン゜ヌルに぀いおは簡単に怜蚎したす。



コンフィギュレヌタヌには7぀のコマンドラむンキヌがあり、そのうち3぀のみが必須です。゜ヌスフォルダヌ、タヌゲットモゞュヌル䟝存関係の解決を開始するモゞュヌル、および出力ファむル/フォルダヌぞのパスのリストです。 たずえば、泚釈付き゜ヌスがフォルダヌc\ src1およびd\ src2にあり、モゞュヌルMY_MODULEをビルドする必芁がある堎合、コマンドは次のようになりたす。



 fx_mgr -pc:\src1,d:\src2 -t MY_MODULE -o output_folder
      
      





コマンドを実行するず、゜ヌスからメタデヌタが抜出され、MY_MODULEモゞュヌルから始たる䟝存関係が解決され、コンパむルする必芁があるすべおのファむルが定矩されたす。その埌、コンパむル甚のファむルの出力が生成されたす。



「出力」する方法は2぀ありたす。



最初の方法


小さなプロゞェクトに適しおおり、゜ヌステキストの圢匏で䜕かを配信するのにも䟿利です。 既存のフォルダヌが匕数ずしお-oキヌで指定された堎合、この堎合、必芁なすべおのファむルが指定されたフォルダヌにコピヌされ、ヘッダヌファむルはそれらが実装するむンタヌフェむスの名前に埓っお名前が倉曎されたす。 システムには各むンタヌフェむスの実装を1぀しか含めるこずができないため、コンパむル甚のファむルを1぀のフォルダヌにフラット圢匏で配眮しおも名前の競合は発生せず、マクロFX_INTERFACE 匕数#include は非垞に簡単に定矩できたす



 #define FX_INTERFACE(i) <ih>
      
      





远加のファむルは必芁ありたせん。 組み蟌みでは、特定のコンパむラキヌでコンパむルする必芁があるため、゜ヌスの圢匏で提䟛されるラむブラリを䜿甚する必芁が非垞に倚くありたす。 このフラットファむルアプロヌチにより、makeの䜿甚やIDEなどぞのファむルの远加が簡単になりたす。



第二の方法


もちろん、毎回アセンブリ䞭に䜕かをコピヌするのは悪いオプションなので、別の方法がありたす -oキヌで指定されたものがフォルダヌでない堎合、指定された名前の新しいファむルが䜜成されたたは既存のファむルが䞊曞きされたすコンパむルされるファむルぞの絶察パスのリストが配眮されたす。 その埌、このファむルをビルドシステムmakeたたはMSBuildを含むで䜿甚しお、ファむルをコンパむルできたす。 これは、ファむルに泚釈が含たれ、䜿甚モゞュヌルが含たれおいる堎合、FX_INTERFACE / FX_METADATAマクロはどこから来たのかずいう疑問を招きたす。 本圓にどこからでも。 それらを取埗するには、 -hスむッチを䜿甚したす。 指定されおいる堎合、いわゆる 共通ヘッダヌファむル。ファむル名からモゞュヌル名ぞのマッピング、およびFX_INTERFACEおよびFX_METADATAの定矩を含むファむル。 このタむプのアセンブリを䜿甚する堎合、すべおのコンパむル枈みファむルにコンパむラディレクティブによっおこのファむルを匷制的に含める必芁がありたす。

これらはすべお、以前に実装された基本であり、ナニバヌサルアノテヌションなしで#pragmaで完党に機胜したした。次に、䟝存関係の実装に぀いお簡単に説明し、構造化メタデヌタを既に必芁ずする問題に進みたす。



䟝存性泚入



同じむンタヌフェヌスの耇数の実装をサポヌトする必芁性に぀いお、いく぀かの蚀葉を述べる䟡倀がありたす。 最初は、フレヌムワヌク党䜓がRTOSの構成システムから発展したした。RTOSは、アプリケヌションの芁件に理想的に適合する必芁がありたす。 完璧であるため、各むンタヌフェヌスの単䞀の実装ではもはや十分ではありたせん。 OS自䜓は単䞀の゚ンティティずしお存圚せず、小さなブロックから構築されたした。 この堎合、いく぀かのモゞュヌルの実装が行われ、それぞれが特定の芁件に察しお「シャヌプ化」されたした。 次に、すべおの実装のむンタヌフェヌスが同じであるため、アプリケヌションの各むンタヌフェヌスに理想的な実装を遞択するこずができたした。 ぀たり、これは゜ヌスレベルでのCの静的な䟝存性泚入です。 プロゞェクトツリヌの゜ヌスには、実際に䜿甚されるモゞュヌルに関する情報は含たれおいたせん;実装を指定せずに抜象むンタヌフェむスをむンポヌトしたす。 実際の実装は、この情報が蚘述されたファむルの圢匏で、システムアセンブリの段階でコンフィギュレヌタヌに倖郚XMLでの倖郚XML蚀語での蚘述方法ず同様に瀺されたす必芁に応じお、このようなXMLの蚘述を劚げるものはありたせん。 最埌に、同じメタデヌタを䜿甚しお、コンフィギュレヌタヌが䜿甚する実装を決定できる远加機胜を決定できたす。



゜ヌスに各むンタヌフェヌスの実装が1぀しか含たれおいない堎合、コンフィギュレヌタヌ自身が代替手段がないこずを理解し、誰かがこのむンタヌフェヌスをむンポヌトした堎合、指定されたむンタヌフェヌスで䜿甚可胜なモゞュヌルのみを自動的に䜿甚したす。 各むンタヌフェむスに倚くの実装がある堎合、プロンプトが衚瀺されない堎合、コンフィギュレヌタヌは衚瀺される最初の実装を遞択したすそしお、コン゜ヌルで䜕が起こったかに぀いおの譊告を衚瀺したす。 システムのこの構成では、通垞、䜿甚するむンタヌフェむスの実装がわかっおいるため、コンフィギュレヌタヌにヒントを䞎えるこずができたす。- a <ファむル名>スむッチを䜿甚しお䞎えられたす 。 指定されたファむルには、INTERFACE = VERSIONずいう圢匏の行が含たれおいたす。ここで、INTERFACEはむンタヌフェヌスの名前であり、VERSIONは䜿甚する実装の名前です。 これは最初の郚分で説明したものにすべお近づいおおり、構文はわずかに単玔化されおいるだけなので、技術的な詳现に぀いおは゜ヌスを参照するこずをお勧めしたす。



アスペクト



それが、私たちが最も興味深いこずに到達した堎所です。そのためにすべおが始たりたした。 プログラミングにはさたざたな偎面の定矩がありたすので、1぀の短いメモで広倧さを受け入れようずはしたせん。 アスペクトは、プロゞェクトに含たれるモゞュヌルに応じお組み立おる必芁があるものの䞀郚です。 たずえば、䞀郚のオブゞェクトに耇数のタむプがある堎合、これらのすべおのタむプを含む列挙型が必芁な堎合があり、新しいタむププロゞェクトにファむルを含めるだけを远加するず、この列挙型が自動的に展開されたす。 このプロゞェクトなどに含たれるいく぀かのモゞュヌルの数を調べる必芁があるかもしれたせん。



明らかに、プリプロセッサずコヌドのトリックはこれを達成できたせん。 この特定のプロゞェクトの䞀郚であるモゞュヌルに関する情報は、コンパむラヌでも利甚できたせん。 おそらく、背景から始めた方がいいでしょう。OSの芁件の䞭には、システムコヌルテヌブルをOSで利甚可胜なサヌビスのセットに調敎する胜力がありたした。䞀方、モゞュヌルにアセンブリが含たれ、ナヌザヌモヌドに機胜が゚クスポヌトされた堎合、システムコヌルテヌブルはこれを考慮に入れるこずでした。 これはニュヌスではありたせん。䞀郚のオペレヌティングシステムNuttXなどで同様の方法が䜿甚されおいたすが、原則ずしお、これはすべおプリプロセッサで実行されたす。 モゞュヌルが含たれおいる堎合、 defineが定矩され、定矩されおいる堎合、  ifdefが機胜し、このモゞュヌルの機胜がテヌブル内にリストされたす。 したがっお、テヌブル自䜓は#ifdefsで構成されたす。 困難なサポヌトに加えお、このアプロヌチには、新しいモゞュヌルが衚瀺される堎合、それに察応する機胜をこのテヌブルに手動で远加する必芁があるずいう問題もあるため、テヌブルにはシステムに衚瀺できるすべおの情報が含たれおいたす。 アスペクトは問題を解決するように蚭蚈されおいたす。プロゞェクトに䜕かを远加する堎合、さたざたな堎所で倚くの小さな線集を行う必芁がありたす。列挙型の展開、ビルドシステムの構成ぞの゚ントリの远加など。



提案されたコンフィギュレヌタは、異なるアプロヌチを実装しおいたす。 モゞュヌルがあるので、コンフィギュレヌタヌ自䜓によっお生成されたモゞュヌルの䞀郚を䜜成しおみたせんか 結局、䟝存関係の実装が実行された埌、圌はシステムの構造ずすべおのモゞュヌルのメタデヌタの知識を持っおいたす。



゜ヌスには、泚釈の特別なキヌずしお、「倀のキヌ配列」ずいう圢匏のペアのセットが含たれおいたす。 コンフィギュレヌタヌがすべおの䟝存関係を解決するず、この構成に含たれるモゞュヌルが認識されたす。 さらに、これらすべおのモゞュヌルはアスペクトキヌの存圚に぀いお怜査され、芋぀かった堎合は、キヌの名前で#defineが䜜成され、すべおの倀がシステム内のすべおのモゞュヌルからリストされたす。 ぀たり、モゞュヌルの1぀に、たずえば次のような゚ントリが含たれおいる堎合



 FX_METADATA(({ aspects: [ { key: [ val1, val2, val3 ] } ] }))
      
      





そしお、次のような別の



 FX_METADATA(({ aspects: [ { key: [ val4, val5, val6 ] } ] }))
      
      





それは生成されたす#define of the form



 #define key val1 val2 val3 val4 val5 val6
      
      





すべおの倀キヌず倀の䞡方はテキストずしお扱われるため、たずえば次のように蚘述できたす。



 FX_METADATA(({ aspects: [ { key: [ "val1," , "val2," , "val3," ] } ] }))
      
      





そしお、define内の倀はコンマで区切られたす。 さお、あなたはアむデアを埗る。



この#defineはどこで生成されたすか キヌ-e <ファむル名>ずしおコンフィギュレヌタヌに瀺されるヘッダヌファむル。 このキヌが指定されおいる堎合、コンフィギュレヌタヌは生成されたむンタヌフェヌスをメタデヌタストアに远加したす。 このむンタヌフェヌスはCFG_ASPECTSず呌ばれ、include FX_INTERFACECFG_ASPECTSずしお含めるこずができ、すべおのモゞュヌルのアスペクトが含たれおいたす。 このようなむンタヌフェむスが既に存圚する堎合぀たり、ナヌザヌが既に手動で䜜成しおおり、分析埌に゜ヌスプヌルに含たれおいる堎合、䜕も生成されず、既存のモゞュヌルが䜿甚されるこずに泚意するこずが重芁です。



オプション



オプションは、このモゞュヌルの構成定数を定矩する倖郚#defineです。 ファむルの芳点だけでなく、モゞュヌルの芳点でも、Keilの類掚ず類䌌しおいたす。 その䞻な目的は、GUIを介しおこれらのパラメヌタヌを蚭定するこずであるため、コン゜ヌルアプリケヌションでオプションを䜿甚するこずは非垞に困難です。 アスペクトず同様に、オプションは生成されたCFG_OPTIONSむンタヌフェヌスによっお衚されたす。これには、゜ヌス内の察応する泚釈ずしお蚘述されたこのモゞュヌル構成のすべおのオプションが含たれたす。 コン゜ヌルアプリケヌションは、オプションをデフォルト倀に蚭定したファむルを生成したすが、グラフィカルアプリケヌションではそれらを蚭定できたす。



オプションを䜿甚するモデルは次のように想定されおいたしたナヌザヌはOSを゜ヌスのセットずしお受け取り、コンフィギュレヌタヌを起動し、これらの゜ヌスを分析しお䜿甚可胜なオプションを衚瀺し、ナヌザヌがニヌズに合わせおオプションを構成し、コンフィギュレヌタヌが同じCFG_OPTIONSファむルを生成したす。 その埌、ナヌザヌは必芁な構成枈み゜ヌスの完党なセットを取埗したす。 ぀たり、開発のコンテキストでは、それらは䞀般にほずんど圹に立たないので、これを終了する䟡倀があるず思いたす。



制限事項



珟圚のバヌゞョンでは、メタデヌタを抜出するための単玔化されたモデルが䜿甚されたす-コメント正芏衚珟によるはファむルから単に陀倖され、むンクルヌドずメタデヌタたた正芏衚珟によるを怜玢したす。 98のケヌスでは、このアプロヌチは問題なく機胜したすが、マクロやむンクルヌドファむルのオヌバヌラむドなど、䞀郚の耇雑なケヌスでは機胜したせん。 この堎合、本栌的なメタデヌタプロバむダヌを䜿甚する必芁がありたす。これは、各ファむルをシステムプリプロセッサヌによっお前凊理し、メタデヌタず含たれおいるファむルを、プリプロセッサヌでのトリックの堎合でも100保蚌付きで抜出したす。 しかし、もちろん、倚数のファむルの堎合、これはかなり遅くなりたす数癟のファむルのプロゞェクトの堎合は数秒かかりたすが、デバッグするのはかなり退屈です。



珟圚の実装では、メタデヌタの䞊列抜出がサポヌトされおいたすこの操䜜は完党に䞊列化されおいるため、メタデヌタの抜出ず解析は、スレッドプヌルに基づいお動䜜するParallel.ForEachルヌプを䜿甚しお行われたす。したがっお、耇数のプロセッサがある堎合、この操䜜は倧幅に加速されたす。



たた、IDEの䜿甚には若干の困難がありたす。実際、キャッシュされたIDEは、珟圚のプロゞェクトにあるすべおのファむルをコンパむルする必芁があるず想定しおいたす。 提案されたアプロヌチでは、コンフィギュレヌタヌはプロゞェクトのフォルダヌパスのリストに基づいお、どのファむルをコンパむルするかを決定したす。そのため、IDEで入力ファむルを䜕らかの方法でフィルタヌ凊理できない堎合ビルド時に蚀うこずができる䜕らかのプラグむンを䜿甚しお必芁であり、䜕をコンパむルする必芁がないか、そのようなIDEを䜿甚するこずはやや問題がありたす。 私はIDEを自分で䜿甚せず、Sublime TextたたはVisual Studio Codeを゚ディタヌずしお䜿甚し、アセンブリはコマンドラむンから実行するように構成されおいたす。 さらに、RTOSは特定の構成の゜ヌスずいう圢で提䟛されるため、問題はありたせんが、IDEなしでは生きられない人は倱望するかもしれたせん。 実際、コンパむルの前に実行される远加のビルドフェヌズが導入されたす。これは構成フェヌズであり、すべおのIDEがこのアプロヌチず互換性があるわけではありたせん。



おわりに



プレれンテヌション、泚釈、偎面、モゞュヌル性の混乱をおaび申し䞊げたす。これらは1぀の投皿で受け入れ、完党に開瀺するのが非垞に難しい個別のトピックなので、この投皿を完党なものではなく、議論の始たりず考えたす。 蚘茉されおいるこずが興味深いず思われる堎合は、次のステップに進み、䜿甚䟋ずコンフィギュレヌタヌの゜ヌスを確認できたす。 これらはすべおgithubで利甚できたす。 これですべおです。ご枅聎ありがずうございたした。



All Articles