C++で作成したDLLとVBAとで文字列の受渡しをするには?

解決


ベッキー  2006-06-27 22:54:54  No: 62343

初めて質問させていただきます
C++でDLLを作成し、それをExcelのVBAから呼出して使っています
数値の受渡しはうまくいっているのですが
文字列の受渡しを行う方法がわかりません

この場合の文字列の受渡し方法を教えて下さい
なお、DLLの中では、単純な数値計算を行っています
C++はVC++.Netを、Excelは2003を使っています


Blue  2006-06-27 23:03:37  No: 62344

WinAPIのように文字列バッファを渡す方法が簡明です。

' VB
Declare Sub Test Lib "xxxx.dll" (ByVal str As String)


Dim str As String

str = String(256, vbNullChar)
Test str
str = Left$(str, InStr(str, vbNullChar)-1)

' VC
void WINAPI Test( char* str )
{
    strcpy( str, "てすと" );
}

文字列バッファを渡したくないのであれば、SysAllocString関数を使うことになります。
' VB
Declare Sub Test Lib "xxxx.dll" (ByRef str As String)


Dim str As String

Test str

' VC
void WINAPI Test( BSTR* str )
{
    SysFreeString( *str );
    *str = SysAllocString( L"てすと" ); // SysAllocStringByteLenの方かも
}


Blue  2006-06-27 23:07:44  No: 62345

ちなみに VB→DLL の一方通行であれば、単に

' VB
Declare Sub Test Lib "xxxx.dll" (ByVal str As String)


Dim str As String

str = "TEST"
Test str

' VC
void WINAPI Test( const char* str )
{
    MessageBox( NULL, str, "", MB_OK );
}

でOK。


Blue  2006-06-27 23:28:14  No: 62346

> SysAllocStringByteLenの方かも
でした。
一応、全パターンのサンプルを載せます。(使わないのもある)

// VC
void WINAPI Sample01A( const char* p )
{
    ::MessageBoxA( NULL, p, "", MB_OK );
}

void WINAPI Sample01W( const wchar_t* p )
{
    ::MessageBoxW( NULL, p, L"", MB_OK );
}

void WINAPI Sample02A( char* p, int size )
{
    const char s[] = "Hello World";
    if ( size >= sizeof( s ) )
    {
        strcpy( p, s );
    }
}

void WINAPI Sample02W( wchar_t* p, int size )
{
    const wchar_t s[] = L"Hello World";
    if ( size >= sizeof( s ) / sizeof( s[ 0 ] ) )
    {
        wcscpy( p, s );
    }
}

void WINAPI Sample03A( BSTR* b )
{
    const char s[] = "Hello World";
    ::SysFreeString( *b );
    *b = ::SysAllocStringByteLen( s, sizeof( s ) - 1 );
}

void WINAPI Sample03W( BSTR* b )
{
    const wchar_t s[] = L"Hello World";
    ::SysFreeString( *b );
    *b = ::SysAllocString( s );
}

BSTR WINAPI Sample04A()
{
    const char s[] = "Hello World";
    return ::SysAllocStringByteLen( s, sizeof( s ) - 1 );
}

BSTR WINAPI Sample04W()
{
    const wchar_t s[] = L"Hello World";
    return ::SysAllocString( s );
}

' VBA
Private Declare Sub Sample01A Lib "VBDLL.dll" (ByVal s As String)
Private Declare Sub Sample01W Lib "VBDLL.dll" (ByVal s As Long)
Private Declare Sub Sample02A Lib "VBDLL.dll" (ByVal s As String, ByVal l As Long)
Private Declare Sub Sample02W Lib "VBDLL.dll" (ByVal s As Long, ByVal l As Long)
Private Declare Sub Sample03A Lib "VBDLL.dll" (ByRef s As String)
Private Declare Function Sample04A Lib "VBDLL.dll" () As String

Sub Test1()
    Dim s As String
    s = "Hello World"
    Sample01A s
    Sample01W StrPtr(s)
End Sub

Sub Test2()
    Dim s As String
    s = String(256, vbNullChar)
    Sample02A s, 256
    s = Left$(s, InStr(s, vbNullChar) - 1)
    MsgBox s
    s = String(256, vbNullChar)
    Sample02W StrPtr(s), 256
    s = Left$(s, InStr(s, vbNullChar) - 1)
    MsgBox s
End Sub

Sub Test3()
    Dim s As String
    Sample03A s
    MsgBox s
End Sub

Sub Test4()
    Dim s As String
    s = Sample04A()
    MsgBox s
End Sub

VARIANTを使う方法もあります・


ベッキー  2006-06-28 02:54:46  No: 62347

Blueさん、ありがとうございます
ご教示いただいた方法でうまくいきました


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

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






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