C++/CLI と C# ライブラリを混在させるときの構成マネージャ

とあるプロジェクトで C++/CLI と C# ライブラリを混在させたときの構成マネージャの記録を残しておきます。ライブラリのほうは、既存のC/C++ライブラリを想定して、それをC#から使いやすいようにラップします。まあ、C#から直接C言語のDLLを呼び出すことは可能なのですが、後々のメンテナンスを考えると、インポート文の羅列はちょっと避けておきたい。C++/CLI を記述するにしても、これもメンテナンスが大変(C++/CLIを知っている人が少ない)なことを考えれば、ある程度C#で書ける部分を多くしておくほうがよいでしょう、という発想で構成を作ってあります。

clip_image010

この構成が妙に複雑なのは、デスクトップアプリ側にサービスとしてC/C++のDLLを利用する部分が存在し、これをストアアプリからローカルHTTPで利用しようとするスタイルのためです。ストアアプリではWin2Dを使っていますが、これがDirectXになると、C++/CXまで参戦するという大混乱状態になりますね…な感じです。

上記のプラットフォームを見ると、x86, Win32, Any CPUが混在していますが、これでokです。プラットフォーム名を「x86」などに揃えようとしたのですが無理でした。ビルドするたびに「構築されているプロジェクトのプロセッサ アーキテクチャ “MSIL” と~」という警告がでますが無視して大丈夫です。

嵌りどころとしては、C++/CLIのプロジェクトを追加したり、ストアアプリのC#プロジェクトを新規に追加したときには、「ビルド」のチェックが外れているということです。参照設定などでプロジェクト参照をしてれば自動的にビルドの順序は設定されるのですが、プラットフォームが異なるせいか、このビルドのチェックが外れたままになっています。C++/CLI と C# デスクトップアプリ、C#ストアアプリを混在させるときは、ここのプラットフォームを選択した後でビルドにチェックをいれておきます。これによってソリューションからリビルドしたときに、普通の C# プロジェクトのように依存関係を見てすべてリビルドされます。そうしないと、ビルドされないまま残った DLL があったりして、正しくビルドができません。

image

参照設定としてややこしかったのは、デスクトップとストアアプリ間のデータを共有するために、C#で作成したPCLを利用するということです。このPCLをシリアライズ/デシリアライズすることで、データ通信を楽にしています。.NETリモートはストアアプリでは使えない(マーシャリングが使えない?)ので、自前でシリアライズする訳ですね。シリアライズ自体は、DataContractSerializerを使っているだけなので難しくはありません。その分データ量が多くなってしまうのですが、まあ、ローカルで通信する分には問題はないでしょう。

これがさっくりと実機で動くかというと、そうでもなくて、

  • VC++ 2013 用の再配布可能パッケージをインストール(msvcp120.dll、msvcr120.dll)
  • netsh でのポート設定
  • 依存するDLLの配置

を適切にやらないとうまく通りません。そういう意味ではオールC#で書いておくと、そのあたりの懸念点は減るのですが…、まあ既存のC/C++のDLL呼び出しのときは、C++/CLIを使いたいところですよね、ってことで、メモ書き的に。

カテゴリー: C# パーマリンク