Passando seqüências de caracteres do VBA para C ++ DLL

Estou realmente confuso sobre a passagem de strings do VBA para C ++. Aqui está o código 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

E o código DLL do C ++:

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);
}

Minha expectativa era que as duas primeiras chamadas para passByBSTRVal e passByBSTRRef funcionassem. Por quê? Porque seqüências de caracteres VBA são objetos COM BSTR. No entanto, ao percorrer o código C ++, o valor de s para ambas as funções era lixo (um monte de kanji). Além disso, a caixa de mensagem exibida era (a mesma). Estou realmente surpreso que as duas primeiras funções não funcionaram.

Minha próxima expectativa era que as duas segundas chamadas passByNarrowVal e passByNarrowRef não funcionassem porque um BSTR é definido como "typedef OLECHAR * BSTR" e um OLECHAR é um tipo de caractere amplo, enquanto LPCSTR é um tipo de caractere restrito. No entanto, ao contrário da minha expectativa, essas duas funções realmente funcionaram. Quando eu percorri o código C ++, o parâmetro s era exatamente o que eu esperava que fosse. Minha expectativa estava errada novamente.

Por fim, minha expectativa para as 2 funções finais (passar por amplo val e ref) era que elas funcionariam, uma vez que um OLECHAR é uma sequência de caracteres largos, portanto um LPCWSTR deve ser capaz de apontar para um BSTR. Mas, como no caso 1 (acho que esses dois casos são idênticos), minha expectativa estava errada. O parâmetro s era composto por caracteres ilegíveis (e a MessageBox exibia os mesmos caracteres ilegíveis.)

Por que minha intuição estava completamente errada? Alguém pode explicar o que não estou entendendo aqui?

questionAnswers(4)

yourAnswerToTheQuestion