Передача строк из VBA в C ++ DLL

Я действительно запутался в передаче строк из VBA в C ++. Вот код VBA:

Private Declare Sub passBSTRVal Lib "foo.dll" (ByVal s As String)
Private Declare Sub passBSTRRef Lib "foo.dll" (ByRef s As String)
Private Declare Sub passByNarrowVal Lib "foo.dll" (ByVal s As String)
Private Declare Sub passByNarrowRef Lib "foo.dll" (ByRef s As String)
Private Declare Sub passByWideVal Lib "foo.dll" (ByVal s As String)
Private Declare Sub passByWideRef Lib "foo.dll" (ByRef s As String)

Sub foobar()
    Dim s As String, str As String
    str = "Hello There, World!"

    s = str
    Call passByBSTRVal(s)
    s = str
    Call passByBSTRRef(s)
    s = str
    Call passByNarrowVal(s)
    s = str
    Call passByNarrowRef(s)
    s = str
    Call passByWideVal(s)
    s = str
    Call passByWideRef(s)
End Sub

И код C ++ DLL:

void __stdcall passByBSTRVal( BSTR s )
{
    MessageBox(NULL, s, L"Pass BSTR by value", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByBSTRRef( BSTR *s )
{
    MessageBox(NULL, *s, L"Pass BSTR by ref", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByNarrowVal( LPCSTR s )
{
    USES_CONVERSION;
    MessageBox(NULL, A2W(s), L"Pass by Narrow Val", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByNarrowRef( LPCSTR* s )
{
    USES_CONVERSION;
    MessageBox(NULL, A2W(*s), L"Pass by Narrow Ref", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByWideVal( LPCWSTR s )
{
    MessageBox(NULL, s, L"Pass by Wide Val", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByWideRef( LPCWSTR* s )
{
    MessageBox(NULL, *s, L"Pass by Wide Ref", MB_OK | MB_ICONINFORMATION);
}

Я ожидал, что первые два вызова passByBSTRVal и passByBSTRRef будут работать. Зачем? Потому что строки VBA являются объектами COM BSTR. Однако во время пошагового выполнения кода C ++ значение s для обеих этих функций было мусором (куча иероглифов). Кроме того, отображаемое окно сообщения было (то же самое). Я действительно удивлен, что первые две функции не сработали.

Следующим моим ожиданием было то, что вторые два вызова passByNarrowVal и passByNarrowRef не будут работать, потому что BSTR определен как «typedef OLECHAR * BSTR», а OLECHAR - это тип широких символов, а LPCSTR - тип узких символов. Однако, вопреки моим ожиданиям, эти две функции действительно сработали. Когда я прошел через код C ++, параметр s был именно тем, что я ожидал. Мои ожидания снова не оправдались.

Наконец, я ожидал, что последние 2 функции (проходящие через широкие значения val и ref) будут работать, поскольку OLECHAR - это строка широких символов, поэтому LPCWSTR должен указывать на BSTR. Но как и в случае № 1 (я полагаю, эти два случая идентичны), мои ожидания были неверными. Параметр s был составлен из символов мусора (и MessageBox отображал те же символы мусора.)

Почему моя интуиция была совершенно не права? Может кто-нибудь объяснить, что я здесь не понимаю?

Ответы на вопрос(4)

Ваш ответ на вопрос