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?