ホーム ] C++ネイティブDLL ] 試作第1号 ] 試作第2号 ]

上へ
C++ネイティブDLLの開発
VBから参照
配列の引き渡し

C++ネイティブDLL

配列の参照引き渡し

最終更新日:2007/04/09  修正

●概要

 次に、VBで準備した配列を渡したり、VBで準備した結果用の配列に、DLLが直接アクセスできるようにする。

●参照渡し

 VBでは、ByRef とすれば、変数のアドレスが渡されることと同じ。変数が配列であれば、実は配列の先頭要素をByRefすれば良い。

 C++ 側では、参照で受ける場合、ポインタとすれば良い。そのポインタが何の型へのポインタであるかを指定すれば、配列かどうかは暗黙の了解で良い。危険であるが、何でも有りの状態なのである。

 以下に、具体例にて説明する。

○DLL側宣言

 void ImageProcess::Convert(char *bb, int w, int h, double a, double b )

  bb はバイトで、ポインタ参照とする。

 これは、char bb[] としても同じ。どちらも、結局は、bb の(先頭)アドレスを示す。こちらであれば、ポインタではなく、配列としてアクセスできるので、より自然となる。

○VB側宣言

  Declare Function Convert Lib "ImageProcessing.dll" Alias "XXX・・・XXXX" (ByRef BB As Byte, ByVal w As Integer, ByVal h As Integer, ByVal a As Double, ByVal b As Double) As Integer

  BBは、バイトの参照とする。実際のコードでは、

  Dim BB(bc) As Byte

  Convert(BB(0), 4, 4, 2.5, 12)

と、バイト配列の先頭要素(BB(0))を指定する。これにより、ImageProcess::Convertは、BB() の先頭アドレスを受けることになる。DLL側が、このアドレスはバイト配列の先頭と思って処理を行えば良いのである。

●DLL呼出しオーバーヘッド

○実測値

 DLLをVBから呼出し、戻ってくるまでの時間(関数内のエントリポイントの検索時間など)が気になるので、実測したところ下図のようになった。

 ImageProcessing.dll に、Sub / Function(Integer型) で、ダミーの関数を定義し、引数は参照型で、画像サイズ分のバイト配列(A()、B())を引き渡すものである。いずれでも、60nS 程度となった。引数は参照渡しなのでサイズに無関係となっており、配列のコピーなどがされていないことも確認できた。

○時間計測で使用したDLL内関数

 ・C++

__declspec (dllexport) void __stdcall cppOverHeadA(unsigned char A[], unsigned char B[])
   {
   }

__declspec (dllexport) int __stdcall cppOverHeadB(unsigned char A[], unsigned char B[])
   {
      return 0;
   }

 ・VB

Friend Declare Sub cppOverHeadA Lib "ImageProcessing.dll" _
(ByRef A As Byte, ByRef B As Byte)

Friend Declare Function cppOverHeadB Lib "ImageProcessing.dll" _
(ByRef A As Byte, ByRef B As Byte) As Integer

 ただ、60nS と言うと、Double 乗算が60回以上できる時間なので、例えば、画素単位でDLLをコールするのは余りにも効率が良くない。DLLコールは画像単位や画像行単位などが効率的と言える。