虚飾の王

2013-12-11 なんか

丸一放置してしまった。

子供が二人いると書く暇なくなるってのと、それが落ち着いてからついったーやってたせいですね。

[][]C++→C(DLL)→C#(クラスライブラリ) の続き C++→C(DLL)→C#(クラスライブラリ) の続きを含むブックマーク

id:lord_hollow:20100712:p1 の続き。

ネイティブアプリからC#実装した何らかの機能を呼び出すにはどうすればいいのか、という話。

前回書いた方法では、呼び出し元になるexeと、仲介役になるDLL(C++/CLI)と、そして機能実装するDLL(C#)という三つのファイル存在してしまうという問題がありました。つまり、DLLが一個多い。

この状態にどうしても納得できない私が三年半の歳月を通じてついにDLLを一つ減らす方法にたどり着きましたのでそれをご紹介しましょう。心して聞くように。

きっかけは、↓を見つけたことでした。

http://blogs.msdn.com/b/junfeng/archive/2006/05/20/599434.aspx

内容は特に解説しませんが、C++/CLIのリンカのオプションで、CSC(C#コンパイラ)の/target:module オプションを付けることで生成される .netmodule というファイルを渡せば双方がリンクできる、ということが書いてあります

こいつらにできることがVisualStudio(MSBuild)にできないはずがない。

というわけで、さっそく私がたどりついたその方法解説していきます。こうすればもっと簡単だよね〜という情報があったら是非ほしいところ。

スタートは、前回のラスト状態です。__declspec(dllexport)がついた関数定義しているC++/CLIプロジェクトが一つと、そのプロジェクトによって参照設定されているC#クラスライブラリプロジェクトが一つある状態


1. C++/CLIプロジェクトからC#プロジェクトへの参照設定を解除する。これによって、当然C++/CLI側のプロジェクトコンパイルエラークラスが見つからない!)になる。

2. この操作によって見えなくなったクラス定義を、C++/CLIで頑張ってヘッダファイルに書く。宣言部だけでOK。実装不要。この作業はめんどくさいので、あらかじめC++/CLIから必要になるC#定義は、できるだけシンプルにしておく。つまり、C++/CLIがexportしているAPIをまとめた小さなクラスインターフェースにしておけ。この定義を変更するとC#C++/CLIの双方に変更が必要になるので、インターフェースのほうがいいかも。インターフェースにする場合は、gcnewができないので別途ファクトリメソッド必要になりますが、その辺はまぁ各自工夫していただくということで。

3. このヘッダファイル必要に応じてincludeすれば、少なくともコンパイルは通る。でもリンクが通らない。実装がないから。この実装を、C#から持ってくる必要がある。

4. おもむろにC#プロジェクトファイル(csproj)をテキストエディタで開いて、OutputType を Library から Module に書き換える。ついでに、PlatformTarget が X86 になっている場合は AnyCPU に戻しておく。

5. この状態C#プロジェクトビルドすると、.DLLの代わりに .netmodule というファイルが出力される。この中に、さっきC++/CLIで頑張って宣言を書いたクラス実装が入っているはずだが、確認する術を私は持たない。

6. C++/CLIプロジェクトに戻って、リンカオプションの「入力」、「追加の依存ファイル」のところに、先ほど生成した.netmoduleのパスを設定してからビルドすると・・・定義が間違っていない限り、リンクも通る!!.netmoduleってのはようは静的リンクライブラリなので、実行時には不要!!!ちなみに、2.で書いたクラス定義が間違っていると、メタデータが一致しないとか言って怒られます。4.でAnyCPUになっていないと、LINK1302エラーが出ます


以上です。C#で書いたクラス定義を再度C++/CLIで書き直さなければならないのが面倒ですが、refrectorとにらめっこして頑張りましょう。

参考のために、嵌ったところを下に列挙しておきます

  • event に [MethodImpl(MethodImplOptions::Synchronized)] という属性勝手についてる場合がある-ポインタを渡せないので引数で結果を受けたければ参照型にしなければならない。C++/CLIの参照型はたとえば int% と書く。
  • クラスそのものの可視性もC++/CLIC#で合わせる必要がある。もともとクラスライブラリだったのでpublicがついているはずだが、静的リンクするようになるのでpublicでなくても別にかまわない。
  • bool型を使う場合は、C#宣言の側に[MarshalAs(UnmanagedType.U1)]とか[return: MarshalAs(UnmanagedType.U1)]を付けなければならない

#20160717追記

2.は不要で、代わりにC++/CLIソースコードに #using "xxxx.netmodule"と書いて(追加の#usingディレクトリ(/AL)設定も確認!)おけばインテリセンスも効く。

2012-10-23 寒ー

なんか・・・いきなり寒いな。

先週まで半そでだったのに今日は長袖でも凍え死ぬかと思った

追伸(嫁に書けといわれたので)

娘が予防接種を受けたらしいのですが、「四歳だから!」と言って泣かなかったそうです。すごいね。

[][][]PhantomPain3 PhantomPain3を含むブックマーク

スレには何度か投入してますが、chaika用のスキンを作っていますライセンスどうしようかな。BSDでいいか

https://github.com/lordhollow/PhantomPain

なんか規制かかっててかけなかったのでこっちに書いた。

[]持ってくるもの:筆入れ 持ってくるもの:筆入れを含むブックマーク

( ゜Д゜)<フレディじゃねぇよ!!

2012-10-22 目が・・・・

なんか仕事モニター凝視しすぎて目が痛くなってきた。

で、なんか画面がちらちらするなーそろそろ帰ろうかな〜と思ったけど良く見るとモニタードット欠けしてた。昔は欠けてなかったと思うからなんか経年劣化なんかな。

[][]犬 犬を含むブックマーク

また短編で新キャラ・・・

ハサミの回を見るに、なんかとんでもない何かがある・・・様にみせかけてなんもなさそうだな。

[]おかずだよ!! おかずだよ!!を含むブックマーク

( ゜Д゜)<いや、どう見ても虫がかってに入ったんだろ

2012-10-21 発表会

娘の習い事の発表会でした。ハンドベルオペレッタを披露。まぁ、4歳なのでそんなたいしたもんじゃないですけど、一生懸命やってる様子はイイですね。

昼ごはんマックマジでメニューなくなっててウザいことこの上ない。まぁケータイクーポンからハッピーセットとなんかセット頼むだけだから影響は少ないけれど。ああ、ハッピーセットプリキュアおもちゃだいぶ揃ってきた。あと2種類かな?

で、その後近所のイオンプリキュア映画公開記念だとかでビンゴ大会をやってたので参加。映画パンフとかポスターとかチケットとかあたるのですが、残念ながらハズレ。パンフ欲しかったんだがなー。娘は「ビンゴ」って上手く言えなくて「りんご大会」って言ってましたが。

で、夜。オリオン座流星群の極大日だというので娘と夜の散歩に行ってきましたが、オリオン座が全くでていないぐらい時間が早かったので流れ星は見えませんでした。娘は一個見つけたといっていますが、さて。

[]ビンゴマスター ビンゴマスターを含むブックマーク

( ゜Д゜)<ハンズで手に入る全てのビンゴカードを入手済みだから自前のカードチートし放題!!

2012-10-20 バッテリー

幼稚園のバザーイベントでした。

そこに行く前に近所の「ご自由にどうぞ」な休耕田のコスモス畑でちょっくらお花を拝借したのですが、花を摘んでる間ハザードを炊いていただけなのにバッテリー上がった\(^o^)/

でもたまたまそこがディーラーショップから徒歩五分のところだったので、電話したらぴょーんとやってきてブースターケーブル繋いでエンジン起動できてDまで行ってバッテリー交換して事なきを得る。約二万円也。高いんだか安いんだか良く分からんけど他に選択肢はなかったんや!!

で、バッテリー交換後予定より少し遅れてバザー会場へ。あと10分遅れてると嫁が任されてる店番をブッチするところだったのです!!

ちなみに、このバザーイベントはまぁ文化祭みたいなもんだと思ってくれれば大体一致する。模擬店の運営は当然生徒(園児)ではなくてその親な。

そこでしばらく遊んだ後、嫁の店番が終わるまで近所の公園で遊ぶ。嫁と合流後三時間公園で遊んでラーメン食って帰った。そしたらみんな疲れて寝てしまったので一人さびしく起きて酒飲みながら日記書いてる俺。

今朝は早くから出発してしまっていたので家の中はぐちゃぐちゃの腐海状態だよ\(^o^)/

[]バザーの定番といえば・・・ バザーの定番といえば・・・を含むブックマーク

( ゜Д゜)<いや、使用済み制服って高校のバザーでそれは怪しい・・・

Connection: close