VC作成DLLをVB.NETで使用するには?

解決


matsu  2006-11-30 07:14:23  No: 97301

度々で申し訳ありません。
OS:windowsXP Pro SP2
VC.NET2003, VB.NET2003

(VC側)
①extern "C" __declspec(dllexport) SAFEARRAY* __stdcall test1(LPCTSTR lp);
②extern "C" __declspec(dllexport) BSTR __stdcall test2(long ld, BOOL b = TRUE);

(VB側)Module1
Declare Function test1 Lib "xxx.dll" (ByVal s As String) As String()

Declare Unicode Function test2 Lib "xxx.dll" _
    (ByVal ld As Long,Optional ByVal b As Long = True) As String

(VB側)Form1
Dim str() As String
str = test1("123")
MsgBox(str(0))

Dim s As String
s = New String(CChar(" "), 256)
s = test2(20000)
MsgBox(s)

まず、①の呼出しで
'System.Runtime.InteropServices.MarshalDirectiveException' のハンドルされていない例外が test2.exe で発生しました。
追加情報 : return valueをマーシャルできません。
となります。
②では
True, Falseのどちらを設定してもFalseの時の値しか戻ってきません。
VB側の記述方法に問題があると思い、いろいろ調べたのですが、
解決策がわかりません。

よろしくお願いします。


Blue  2006-11-30 10:08:43  No: 97302

丸付き数字は使わないほうがいいです。

(1)とりあえず
http://msdn2.microsoft.com/ja-jp/library/z6cfh6e6(VS.80).aspx
をよんでみてください。
おそらく、<MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_BSTR)> のような指定が必要なんでしょう。
# VB.NETでDeclareはあんまつかわないから微妙。(全部DllImportで書くから)

(2)VB6やVBAと違って、LONG型(=long int型),BOOL型(=int型)はLong型ではありません。
   Integer型もしくはSystem.Int32型を使ってください。
   (Long型はSystem.Int64つまりVCでいうint64型です)
それと、TRUEは1の#defineですので、Optionalを指定するのであれば、
Trueではなく1を指定したほうがいいです。


matsu  2006-12-01 07:33:51  No: 97303

Blueさん、いつもすみません。
専属トレーナーみたいになって申し訳ないです。

(2)は以下で解決しました。ありがとうございます。
<DllImport("D:\Visual Studio Projects\VC\ComProc\Release\ComProc.dll", _
    CharSet:=CharSet.Unicode)> _
Public Function test2( _
    ByVal a As System.Int32, _
    Optional ByVal b As System.Int32 = 1) As String
End Function

(1)で悩んでます。msdnは見ましたが難しいです。
以下では同じエラーになります。

(VB.NET)Module1
Imports System.Runtime.InteropServices
<MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_BSTR)> _
    Public str() As String
(VB.NET)Form1
Imports System.Runtime.InteropServices
str = test1("123", "あああ") -----> ここでエラー
MsgBox(str(0))

また「ちがうっぽ。」と怒られそうですが
よろしくお願いします。


Blue  2006-12-01 07:54:35  No: 97304

ん〜

実験したコードです。
# (1)のは以前解答したもの

VC,DLL
SAFEARRAY* WINAPI Sample21()
{
    SAFEARRAYBOUND sb;
    sb.lLbound   = 0;
    sb.cElements = 3;
    SAFEARRAY* psa = ::SafeArrayCreate( VT_BSTR, 1, &sb );
    
    //BSTR* data;
    //::SafeArrayAccessData( psa, ( void** )&data );
    //
    //data[ 0 ] = ::SysAllocString( L"イチロー" );
    //data[ 1 ] = ::SysAllocString( L"松井秀喜" );
    //data[ 2 ] = ::SysAllocString( L"松坂大輔" );

    //::SafeArrayUnaccessData( psa );

    ::SafeArrayLock( psa );
    long i;
    i = 0;
    ::SafeArrayPutElement( psa, &i, ::SysAllocString( L"イチロー" ) );
    i = 1;
    ::SafeArrayPutElement( psa, &i, ::SysAllocString( L"松井秀喜" ) );
    i = 2;
    ::SafeArrayPutElement( psa, &i, ::SysAllocString( L"松坂大輔" ) );
    ::SafeArrayUnlock( psa );

    return psa;
}

BSTR WINAPI test2(long ld, BOOL b = TRUE)
{
    if (b)
        return ::SysAllocString(L"斉藤隆");
    return ::SysAllocString(L"田口壮");
}

VB
Module Module1

    Declare Unicode Function Sample21 Lib "VBDll.dll" () As <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_BSTR)> String()
    Declare Unicode Function test2 Lib "VBDll.dll" _
        (ByVal id As Integer, Optional ByVal b As Integer = 1) As String

    Sub Main()
        Dim a() As String

        a = Sample21()
        For Each name As String In a
            MsgBox(name)
        Next

        Dim s As String
        s = test2(0)
        MsgBox(s)
        s = test2(1, 0)
        MsgBox(s)
    End Sub

End Module


matsu  2006-12-01 08:12:03  No: 97305

Blueさんへ
迅速、的確で丁寧なご指導、ありがとうございます。

やはり「ちがうっぽ。」でしたね。
申し訳ありません。

VB
Module Module1

<DllImport("D:\Visual Studio Projects\VC\ComProc\Release\ComProc.dll")> _
Public Function test1( _
    ByVal a As String, _
    ByVal b As String) As <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_BSTR)> String()
End Function

Form1

Dim str() As String
str = test1("123", "あああ")
MsgBox(str(0))

で解決しました。

ありがとうございました!!


Hongliang  URL  2006-12-01 10:24:10  No: 97306

メモリの解放について意識してるんだろうか。
// 私も BStr を返値としてマーシャリングさせた場合はその途中で解放されるってことくらいしか知らないけれど。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加