VBフォームの訂正だけど、コマンドプロンプトでDLL?

|

前々回の「VBフォーム(Windows アプリケーション)だって、コマンドプロンプトでDLL?」記事で、"VBフォームからDLLを呼び出す場合、上記エイリアスの手法を .def ファイル内で使用する必要があるらしい"と書きましたが、ちょっと違っていたようです。

マイクロソフトのドキュメントに、

Visual Basic で書かれたプログラムから DLL を呼び出す場合は、ここで示したエイリアスの手法を .def ファイル内で使用する必要があります。エイリアスが Visual Basic プログラムの中で宣言されている場合は、.def ファイル内でのエイリアスは不要です。これは、Visual Basic プログラムでは、Declare ステートメントにエイリアス句を追加することで実現されます。

とあったのですが、VBフォームでエイリアス句の動作確認をしようとして気が付きました。

訂正で、VBフォーム ⇒ CのDLL、VBフォーム ⇒ C++のDLLを呼び出すだけのサンプルを作ってみました。

<注意点>

・DLLでエクスポートしたい関数などは、.def ファイルに記述する必要があります。

・.def ファイルでも、VBフォームでも、エイリアスは一切必要無さそうです。

・DLLファイルが無かったり、呼び出す関数がエクスポートされていない(.def ファイルに記述が無い)と、VB側で例外が発生します。

・お試し結果の出力は、VBフォームの実行ファイル(.exe)をDOS窓でリダイレクト(> や >>)して得ています。


お試し環境
  WindowsXP 32bit Edition
  Visual C++ & Visual Basic 2008


/*---- VB Form ⇒ C の dll 作成 --------------- コマンドライン -------------*/

D:\vc2008\dllchk>cl /LD testc.c /link /def:testc.def
(testc.dll を作成)

/*----------------------------------------------------------------------------*/

/*---- VB Form ⇒ C++ の dll 作成 ------------- コマンドライン -------------*/

D:\vc2008\dllchk>cl /LD testpp.cpp /link /def:testpp.def
(testpp.dll を作成)

/*----------------------------------------------------------------------------*/


/*---- VB Form ⇒ C の dll 呼出し ------------ お試し結果 ------------------*/

CPRINT01 : String from Visual Basic : Visual Basic01 です。 - 17
CPRINT02 : Values from Visual Basic : 200

VBPRINT01 Return C String : Hi! Visual Basic
VBPRINT02 Called C : Return from C
VBPRINT02 Return C Values : 40000
EXCEPTION DLL 'testc.dll' の 'subc05' というエントリ ポイントが見つかりません。

/*----------------------------------------------------------------------------*/

/*---- VB Form ⇒ C++ の dll 呼出し ------------- お試し結果 ---------------*/

C++PRINT03 : String from Visual Basic : Visual Basic03 です。 - 19
C++PRINT04 : Values from Visual Basic : 300

VBPRINT03 Called C++ : Return from Visual C++
VBPRINT03 Return C++ String : Hello Visual Basic
VBPRINT04 Return C++ Values : 90000
EXCEPTION DLL 'testpp.dll' の 'subpp06' というエントリ ポイントが見つかりません。

/*----------------------------------------------------------------------------*/

/*---- .def 無しで dll 作成 と .dll 無しでの呼出し ----- 結果 --------------*/

EXCEPTION DLL 'testc.dll' の 'subc01' というエントリ ポイントが見つかりません。

EXCEPTION DLL 'testpp.dll' を読み込めません: 指定されたモジュールが見つかりません。(HRESULT からの例外: 0x8007007E)

/*----------------------------------------------------------------------------*/


/*==== VB Form ⇒ C の dll 呼出し ============= お試しソース ===============*/
/*---- testc.def -------------------------------------------------------------*/

LIBRARY testc
EXPORTS
 subc01
 subc02

/*----------------------------------------------------------------------------*/

/*---- testc.c ---------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>   // strcpy_s 関数

void __stdcall subc01(char *s, int d)
{
    printf("CPRINT01 : String from Visual Basic : %s - %d\n", s, d);
    strcpy_s(s, d, "Hi! Visual Basic");
}

char * __stdcall subc02(int *d)
{
    printf("CPRINT02 : Values from Visual Basic : %d\n", *d);
    *d *= *d;
    return("Return from C");
}

void __stdcall subc05(void)
{
    printf("CPRINT05 : Called C ?\n");
}

/*----------------------------------------------------------------------------*/
/*============================================================================*/


/*==== VB Form ⇒ C++ の dll 呼出し ============= お試しソース =============*/
/*---- testpp.def ------------------------------------------------------------*/

LIBRARY testpp
EXPORTS
 subpp03
 subpp04

/*----------------------------------------------------------------------------*/

/*---- testpp.cpp ------------------------------------------------------------*/

#include <cstdio>
#include <cstring>   // strcpy_s 関数

extern "C" char * __stdcall subpp03(char *s, int d)
{
    printf("C++PRINT03 : String from Visual Basic : %s - %d\n", s, d);
    strcpy_s(s, (unsigned int)d, "Hello Visual Basic");
    return("Return from Visual C++");
}

extern "C" void __stdcall subpp04(int *d)
{
    printf("C++PRINT04 : Values from Visual Basic : %d\n", *d);
    *d *= *d;
}

extern "C" void __stdcall subpp06(void)
{
    printf("C++PRINT06 : Called Visual C++ ?\n");
}

/*----------------------------------------------------------------------------*/
/*============================================================================*/


/*==== VB Form ================================ お試しソース ===============*/
/*----------------------------------------------------------------------------*/

Public Class Form1

    Private Declare Sub subc01 Lib "testc.dll" (ByVal s As String, ByVal d As Integer)
    Private Declare Function subc02 Lib "testc.dll" (ByRef d As Integer) As String
    Private Declare Sub subc05 Lib "testc.dll" ()

    Private Declare Function subpp03 Lib "testpp.dll" (ByVal s As String, ByVal d As Integer) As String
    Private Declare Sub subpp04 Lib "testpp.dll" (ByRef d As Integer)
    Private Declare Sub subpp06 Lib "testpp.dll" ()

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim a As Integer = 17
        Dim d As Integer = 200
        Dim s As String = "Visual Basic01 です。"

        Try
            subc01(s, a)
            Console.WriteLine("VBPRINT01 Return C String : " & Strings.Left(s, InStr(s, Chr(0)) - 1))
            Console.WriteLine("VBPRINT02 Called C : " & subc02(d))
            Console.WriteLine("VBPRINT02 Return C Values : " & d)
            subc05()
        Catch ex As EntryPointNotFoundException
            Console.WriteLine("EXCEPTION " & Err.Description)
        Catch ex As DllNotFoundException
            Console.WriteLine("EXCEPTION " & Err.Description)
        Catch ex As Exception
            Console.WriteLine("EXCEPTION その他の例外が発生しました。")
        End Try
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim a As Integer = 19
        Dim d As Integer = 300
        Dim s As String = "Visual Basic03 です。"

        Try
            Console.WriteLine("VBPRINT03 Called C++ : " & subpp03(s, a))
            Console.WriteLine("VBPRINT03 Return C++ String : " & s)
            subpp04(d)
            Console.WriteLine("VBPRINT04 Return C++ Values : " & d)
            subpp06()
        Catch ex As EntryPointNotFoundException
            Console.WriteLine("EXCEPTION " & Err.Description)
        Catch ex As DllNotFoundException
            Console.WriteLine("EXCEPTION " & Err.Description)
        Catch ex As Exception
            Console.WriteLine("EXCEPTION その他の例外が発生しました。")
        End Try
    End Sub
End Class

/*----------------------------------------------------------------------------*/
/*============================================================================*/