朝会発表テーマ

C#やVB.NETからC/C++の関数を呼び出す

レジュメ

1.問題点

C#やVB.NETで作成されたプログラムは「.NET Framework」という仕組みの上で作成される。
一方C/C++で作成されたプログラムは上記の「.NET Framework」とは無関係に作成される。
そのためC#やVB.NETで作成した関数とC/C++で作成した関数には互換性がない。
そのため、C#やVB.NETからC/C++の関数を呼び出せるようにするためには
下記のいずれかの方法をとる必要がある。

2.解決方法

(1)Component Object Model(COM)形式で、呼び出される側の関数を実装する

COMをサポートしている言語(C#、VB.NETは可能)であれば、
COM形式で実装された関数を呼び出すことができる。

×呼び出す側、呼び出される側共にソースコードが若干複雑になる

→本来COMはアプリケーション間通信に利用される形式であって、
関数を呼び出すのみの目的のためにCOM形式で実装するには実装コストが見合わないと思われる。

(2)C++/CLI言語を利用して呼び出される関数を作成する

C++の拡張言語「C++/CLI」を利用すると、C#やVB.NETから呼び出せる関数を作ることができる。

逆に、C#やVB.NETで作成された関数をC++/CLIから呼び出すことも可能
×厳密にはC++とは異なる言語であり、言語習得のための学習時間が必要
×.NET FrameworkとC/C++でメモリ管理方法が異なるため注意が必要

→一つのアプリケーション内でC#の処理とC++の処理を混在させる
開発で有用かもしれない(画面はC#、裏側の処理はC++など)

(3)DllImport属性を利用して呼び出す

C#やVB.NETにあらかじめ用意されているDllImport属性を使用すると、
DLLファイルに含まれるC/C++で実装された関数を呼び出すことができる。

×プログラミング言語間の型の相違についてプログラマが判断し、
事前にパラメタ設定を行う必要がある(「マーシャリング」と呼ばれる)

→DLLファイルと関数名、引数の型が分かっていれば呼び出せるため、
C/C++側のソースコードがなくても呼び出せる(過去に作成したプログラム資産を使う場合に便利)

3.方法まとめ

解決方法(1) ・・・ 他のアプリケーションと相互通信を行う際に使う。
解決方法(2) ・・・ C#やVB.NETとC/C++との間で、ソースコードレベルで連携が可能。メモリ管理に注意。
解決方法(3) ・・・ 一番簡単に実現可能。言語間の「型」(int、char、string等)の相違に注意。

サンプルプログラム

サンプルプログラム(解決方法(3)を使用。C++で作成した関数をC#から呼び出す)

C++側 ・・・
引数なし、固定の文字列「Hello, world!」を返す関数を実装。
exeではなくdllを作成する。(ファイル名「lib.dll」)
C#側 ・・
C++側で作成した関数を呼び出し、その戻り値をメッセージボックスで表示するプログラム。
プログラム実行前に、exeと同じフォルダにC++側プログラムで作成した「lib.dll」を配置する。

C++側プログラムソース
実行結果

・メッセージボックスが表示される。
・メッセージボックスの中にはC++側関数が返す文字列が表示されている。

C#側プログラムソース

想定質問

Q
COMの場合、言語間のインターフェースはどのように定義するか?
A

COMを使用した場合、プログラミング言語間のインターフェースは
IDLファイル(Interface Fefinition Language)を使ってやりとりする。
このファイルの中に、型やデータのサイズを記述する

Q
C++/CLI言語でプログラムを作成するには?
A

C++/CLIを使ったプログラムはVisual Studioで作成が可能。
プロジェクト設定を変更する必要あり。
C++言語のプロジェクトを作成し、
プロジェクト設定の「CLR(共通言語ランタイム)を使用する」にチェックする。

Q
C++/CLIでメモリ管理が複雑な理由
A

たとえば、C#でメモリの解放を行う処理は、
あらかじめ用意されているライブラリやガベージコレクタで行ってくれるが、
C++/CLI側ではそれをプログラマが自分で実装する必要がある。

(オブジェクト指向でクラスに慣れている人向けの説明)
通常クラスにはコンストラクタとデストラクタが必要だが、
C++/CLIのクラスではそれらに加えてファイナライザという特別な関数も実装する必要がある。

Q
VB.NETのDeclearキーワードとDllImport属性の違い
A

(1)DllImport属性の方がより細かく制御できる
・呼び出し規約
・文字列の扱い

(2)DllImport属性はC#でも使える

コメント