本ページは公開が終了した情報の複製であり、掲載時点での情報です。本ページに記載されている内容について各所に問い合わせることはご遠慮下さい。
サポート技術情報

[VB2] DLLs への引数の渡し方

文書番号: 402600

最終更新日: 2000/01/05


この資料は以下の製品について記述したものです。


この記事は、以前は次の ID で公開されていました: JP402600

概要

この資料は Visual Basic for Windows 2.0 から C 言語等で作成した Dynamic Link Libraries (以下 DLL) を呼び出し、引数を渡す方法をサンプルと共に記述しています。

Declare 宣言方法

  Declare Sub name Lib "library name" (argument list)
  Declare Function name Lib "library name" (argument list) As return type

プロシージャ名の置き換え (Alias)

DLL プロシージャの中には Visual Basic for Windows 2.0 で識別できない名前
(ハイフン“-”など) を持つ場合や予約語と同じ名前を持つ場合があります。こ
れらの場合には Alias キーワードを使用して Visual Basic for Windows 2.0 で
識別できる名前に置き換える必要があります。
  Declare Sub name Lib "library name" Alias "Bad name" (argument list)
  Declare Function name Lib "library name" Alias "Bad name" (argument list) As
  return type

値渡しと参照渡し

Visual Basic for Windows 2.0 の引数は参照渡し (アドレス渡し) になっています
が、一般的には値渡しの場合が多くあります。値渡しで行うには ByVal キーワード
を指定する必要があります。

型宣言の対応

Microsoft(R) Windows(R) Software Development Kit (以下 Windows SDK )で用いら れている各型宣言や C 言語の型宣言と Visual Basic for Windows 2.0 における
型宣言は以下のような対応になります。これを参考にして型宣言を書き換えてください。

整数へのポインタ (LPINT)

  variable name As Integer

長整数へのポインタ (LPDWORD)

  variable name As Long

整数 (INT、WORD、BOOL etc.)、ハンドル (hWnd、hDC etc.)

  ByVal variable name As Integer

長整数 (DWORD、LONG)

  ByVal variable name As Long

void へのポインタ (void *)

  variable name As Any

文字列型

C 言語で扱う文字列は ASCIIZ 文字列 (Null 文字で終了している文字列) です。引
数として ASCIIZ 文字列を渡すときは ByVal キーワードを使用する必要があります。
  ByVal variable name As String
文字列は常に参照渡しになります。ByVal キーワードは値渡しという意味ではなく、 ASCIIZ 文字列に変換して渡すという意味なので注意が必要です。また、DLL プロ
シージャに渡した文字列よりも長い文字列を DLL プロシージャが返した場合には、
他の領域を破壊してしまいますので注意が必要です。

ユーザ定義型

参照渡しであれば、ユーザ定義型全体を一つの引数として引き渡すことが可能で
す。ただし、値渡しで引き渡すことはできませんので注意が必要です。

配列

数値配列の場合は参照渡しであれば、配列全体を一つの引数として引き渡すことが
可能です。ただし、値渡しで引き渡すことや文字列配列全体を一つの引数として
引き渡すことはできませんので注意が必要です。
  Declare Sub name Lib "library name" (variable name As Any)
  ...
  name(array name(0))
また、ヒュージ配列 (64KB よりも大きな配列) の場合は最初の 64KB だけにしか
アクセスすることができませんので注意が必要です。

Null ポインタ

Null ポインタを渡す必要があるときは、その引数を As Any として宣言し、ByVal 0& を渡します。なお、長さが 0 の文字列を渡した場合は、Null 文字列へのポインタが渡さ れます。Null ポインタとしては渡されませんので注意が必要です。
  Declare Sub name Lib "library name" (variable name As Any)
  ...
  name(ByVal 0&)

プロパティ

プロパティは値渡しで行う必要があるため、引数が ByVal で宣言されている場合
のみプロパティを直接渡すことができます。なお、文字列プロパティは参照渡しに
なるため、中間変数を併用する必要があります。また、数値プロパティを参照渡しで 行う場合も同様です。

その他の注意点

  • C 言語で作成されたルーチンは Pascal 呼び出しでなければなりません。
  • 関数ポインタ、符号なし整数型、共用体 (Union)、通貨型、バリアント型、 オブジェクト変数、特殊オブジェクト (App、Screen、Clipboard、Printer、Debug) を引き渡すことはできません。

Visual Basic for Windows 2.0 で発生する主なエラー

35 Sub, Function が定義されていません

Sub プロシージャまたは、Function プロシージャが定義されていません。指定
した DLL 等に含まれているかを確認してください。

48 DLL 読み込み時のエラーです

指定された DLL を読み込むことができません。指定した DLL を再確認してくだ
さい。より詳しい情報は Windows API の LoadLibrary を使用することで得ること
ができます。

49 DLL が正しく呼び出せません

DLL の呼び出し、または引き数の数や型が一致していません。Declare 宣言を
再確認してください。なお、値渡しの場合は ByVal キーワードを付加する必要が
あります。

サンプル プログラム

左側のテキスト ボックスに数値を入力してコマンド ボタンを押します。結果が右側の テキスト ボックスに表示されます。
  +--+-------------------------------------------+--+
  |-|              DLL Call Test                |▼|
  +--+-------------------------------------------+--+
  |+-----------+ +-----------+ +--------+ +--------+|
  ||           | |           | |  整数  | |アドレス||
  |+-----------+ +-----------+ +========+ +========+|
  |              +-----------+ +--------+ +--------+|
  |              |           | | 長整数 | | 文字列 ||
  |              +-----------+ +========+ +========+|
  |              +-----------+ +--------+ +--------+|
  |              |           | | 単精度 | |  配列  ||
  |              +-----------+ +========+ +========+|
  |              +-----------+ +--------+ +--------+|
  |              |           | | 倍精度 | | 構造体 ||
  |              +-----------+ +========+ +========+|
  +-------------------------------------------------+
ここでは DLL を作成するための処理系として Microsoft(R) Visual C++(TM)
Development System for Windows(TM) Version 1.0 を使用しています。他の処理系の 場合は、修正が必要な場合もあります。

メイン プログラム用フォーム ファイル (PASSVB.FRM)

  VERSION 2.00
  Begin Form frmCallTest
     BorderStyle     =   1  '固定 (実線)
     Caption         =   "DLL Call Test"
     Height          =   2550
     Left            =   960
     LinkTopic       =   "Form1"
     MaxButton       =   0   'False
     ScaleHeight     =   2175
     ScaleWidth      =   6045
     Top             =   1260
     Width           =   6135
     Begin CommandButton cmdCallFunc
        Caption         =   "構造体"
        Height          =   495
        Index           =   7
        Left            =   4680
        TabIndex        =   12
        Top             =   1560
        Width           =   1215
     End
     Begin CommandButton cmdCallFunc
        Caption         =   "配列"
        Height          =   495
        Index           =   6
        Left            =   4680
        TabIndex        =   11
        Top             =   1080
        Width           =   1215
     End
     Begin CommandButton cmdCallFunc
        Caption         =   "文字列"
        Height          =   495
        Index           =   5
        Left            =   4680
        TabIndex        =   10
        Top             =   600
        Width           =   1215
     End
     Begin TextBox txtValue
        Height          =   405
        Index           =   4
        Left            =   1800
        TabIndex        =   9
        Top             =   1560
        Width           =   1575
     End
     Begin TextBox txtValue
        Height          =   405
        Index           =   3
        Left            =   1800
        TabIndex        =   8
        Top             =   1080
        Width           =   1575
     End
     Begin TextBox txtValue
        Height          =   405
        Index           =   2
        Left            =   1800
        TabIndex        =   7
        Top             =   600
        Width           =   1575
     End
     Begin CommandButton cmdCallFunc
        Caption         =   "アドレス"
        Height          =   495
        Index           =   4
        Left            =   4680
        TabIndex        =   6
        Top             =   120
        Width           =   1215
     End
     Begin CommandButton cmdCallFunc
        Caption         =   "倍精度"
        Height          =   495
        Index           =   3
        Left            =   3480
        TabIndex        =   5
        Top             =   1560
        Width           =   1215
     End
     Begin CommandButton cmdCallFunc
        Caption         =   "単精度"
        Height          =   495
        Index           =   2
        Left            =   3480
        TabIndex        =   4
        Top             =   1080
        Width           =   1215
     End
     Begin CommandButton cmdCallFunc
        Caption         =   "長整数"
        Height          =   495
        Index           =   1
        Left            =   3480
        TabIndex        =   3
        Top             =   600
        Width           =   1215
     End
     Begin CommandButton cmdCallFunc
        Caption         =   "整数"
        Height          =   495
        Index           =   0
        Left            =   3480
        TabIndex        =   2
        Top             =   120
        Width           =   1215
     End
     Begin TextBox txtValue
        Height          =   405
        Index           =   1
        Left            =   1800
        TabIndex        =   1
        Top             =   120
        Width           =   1575
     End
     Begin TextBox txtValue
        Height          =   405
        Index           =   0
        Left            =   120
        TabIndex        =   0
        Top             =   120
        Width           =   1575
     End
  End
  Option Explicit
  Declare Function noparams Lib "passv.dll" () As Integer
  Declare Function passint Lib "passv.dll" (ByVal a As Integer) As Integer
  Declare Function passlong Lib "passv.dll" (ByVal a As Long) As Long
  Declare Function passfloat Lib "passv.dll" (ByVal a As Single) As Single
  Declare Function passdouble Lib "passv.dll" (ByVal a As Double) As Double
  Declare Sub passpnt Lib "passv.dll" (a As Integer, b As Long, c As Single, d A
  s Double)
  Declare Sub passstr Lib "passv.dll" (ByVal a As String)
  Declare Sub passary Lib "passv.dll" (a As Integer, ByVal b As Integer)
  Declare Sub passstrct Lib "passv.dll" (a As teststruct)
  'Declare Sub passstrct Lib "passv.dll" (a As Any)  ' As Any でも大丈夫
  Sub cmdCallFunc_Click (Index As Integer)
      Dim idt As Integer
      Dim ldt As Long
      Dim sdt As Single
      Dim ddt As Double
      Dim icnt As Integer
      Dim cst As String
      ReDim iary(1 To 4) As Integer
      Dim tstruct As teststruct
      For idt = 1 To 4
          txtValue(idt).Text = ""
      Next idt
      If Index <> 5 And Val(txtValue(0).Text) = 0 Then
          MsgBox ("数値を入力してください")
          txtValue(0).SetFocus
          Exit Sub
      End If
      Select Case Index
          Case 0: ' int 型の値を引数で渡す、結果は戻り値
              txtValue(1).Text = passint(CInt(txtValue(0).Text))
          Case 1: ' long 型の値を引数で渡す、結果は戻り値
              txtValue(2).Text = passlong(CLng(txtValue(0).Text))
          Case 2: ' single 型の値を引数で渡す、結果は戻り値
              txtValue(3).Text = passfloat(CSng(txtValue(0).Text))
          Case 3: ' double 型の値を引数で渡す、結果は戻り値
              txtValue(4).Text = passdouble(CDbl(txtValue(0).Text))
          Case 4: ' int/long/single/double 型のアドレスを引数で渡す、結果は引数自身
              idt = CInt(txtValue(0))
              ldt = CLng(txtValue(0))
              sdt = CSng(txtValue(0))
              ddt = CDbl(txtValue(0))
              passpnt idt, ldt, sdt, ddt
              txtValue(1).Text = idt
              txtValue(2).Text = ldt
              txtValue(3).Text = sdt
              txtValue(4).Text = ddt
          Case 5: ' string 型の文字列記述子を引数で渡す、結果は引数自身
              cst = txtValue(0)
              If Len(cst) < 2 Then cst = cst + "  "
              passstr cst
              txtValue(1).Text = cst
          Case 6: ' int 型の配列および要素数を引数で渡す、結果は引数自身
              passary iary(1), 4
              For icnt = 1 To 4
                  txtValue(icnt).Text = iary(icnt)
              Next icnt
          Case 7: ' 構造体を引数で渡す、結果は引数自身
              tstruct.id = CInt(txtValue(0).Text)
              tstruct.ld = CLng(txtValue(0).Text)
              tstruct.fd = CSng(txtValue(0).Text)
              tstruct.dd = CDbl(txtValue(0).Text)
              tstruct.sd = txtValue(0).Text
              passstrct tstruct
              txtValue(1).Text = tstruct.id
              txtValue(2).Text = tstruct.ld
              txtValue(3).Text = tstruct.fd
              txtValue(4).Text = tstruct.dd
              txtValue(0).Text = tstruct.sd
          End Select
  End Sub

メイン プログラム用モジュール ファイル (PASSVB.BAS)

  Option Explicit
  Type teststruct
      id As Integer
      ld As Long
      fd As Single
      dd As Double
      sd As String * 6
  End Type

DLL ソース ファイル (PASSV.C)

  #define STRICT
  #include <windows.h>
  #include <string.h>
  /* 関数型: int, 引数: int, 戻り値: 引数の 2 倍 */
  int far _pascal _export passint(int a)
  {
      return a * 2;
  }
  /* 関数型: long, 引数: long, 戻り値: 引数の 2 倍 */
  long far _pascal _export passlong(long a)
  {
      return a * 2;
  }
  /* 関数型: float, 引数: float, 戻り値: 引数の 2 倍 */
  float far _pascal _export passfloat(float a)
  {
      return a * (float)2.0;
  }
  /* 関数型: double, 引数: double, 戻り値: 引数の 2 倍 */
  double far _pascal _export passdouble(double a)
  {
      return a* (double)2.0;
  }
  /* 関数型: void, 引数: int, long, float, double のポインタ */
  /* 結果: 引数の値を 2 倍にして返す */
  void far _pascal _export passpnt(int _far *a, long _far *b, float _far *c, dou
  ble _far *d)
  {
      *a = *a * 2;
      *b = *b * 2;
      *c = *c * (float)2.0;
      *d = *d * (double) 2.0;
      return;
  }
  /* 関数型: void, 引数: int の配列 */
  void far _pascal _export passary(int _far a[], int idx)
  {
      int i;
      for (i=0;i<idx;++i){
          a[i] = i;
      }
      return;
  }
  /* 関数型: void, 引数: 構造体, 結果: 各要素の値を 2 倍にして返す */
  typedef struct TESTSTRUCT{
      int         id;
      long        ld;
      float       fd;
      double      dd;
      char        sd[6];
  }FAR * LPSTRUCT;
  void far _pascal _export passstrct(LPSTRUCT lps)
  {
      lps->id = lps->id * 2;
      lps->ld = lps->ld * 2;
      lps->fd = lps->fd * (float)2;
      lps->dd = lps->dd * (double)2;
          _fstrncpy(lps->sd,"change",6);
      return;
  }
  /* 関数型: void, 引数: char のポインタ, 結果: 文字列の先頭 2 バイトを ** にして
  返す */
  /* void far _pascal _export passstr(LPSTR a) */
  void far _pascal _export passstr(char _far *a)
  {
      _fstrncpy (a, "**",2);
      return;
  }

DLL 用モジュール定義ファイル (PASSV.DEF)

  LIBRARY PASSV
  EXETYPE WINDOWS
  DATA    PRELOAD MOVABLE SINGLE
  CODE    PRELOAD MOVABLE DISCARDABLE

LoadLibrary による“ DLL 読み込み時のエラーです”の解析

"DLL 読み込み時のエラーです" というエラーが発生した場合、Windows API の Load Library を使用することで、発生したエラーの詳細を得ることが可能です。エラー
コードの意味に関しましては Windows SDK のマニュアルを参照してください。

サンプル コード

  Declare Function LoadLibrary Lib "Kernel" (ByVal f$) As Integer
  Declare Sub FreeLibrary Lib "Kernel" (ByVal h As Integer)
  Dim hInst As Integer
  hInst = LoadLibrary(library name)
  If hInst > 32 Then
      MsgBox "LoadLibrary success"
      FreeLibrary (hInst)
  Else
      MsgBox "LoadLibrary error: " & Format$(hInst)
  End If

Keywords: KBHOWTO KB402600
Technology: kbAudDeveloper kbVBSearch

inserted by FC2 system