I have this code in my VB6 app:
Private Declare Function FileGetParentFolder Lib "Z-FileIO.dll" _
(ByVal path As String) As String
Output.AddItem FileGetParentFolder(FileText.Text)
Output is a list, FileText is a text field containing a file path. My C++ DLL contains this function:
extern "C" BSTR ZFILEIO_API FileGetParentFolder(Path p)
{
try {
return SysAllocString(boost::filesystem::path(p).parent_path().c_str());
} catch (...) {
return SysAllocString(L"");
}
}
where Path
is typedef'd as LPCSTR
. The argument comes into my DLL perfectly, but whatever I try to pass back, the VB6 app shows only garbage. I tried several different methods with SysAllocStringByteLength
, casting the SysAllocString
argument to LPCWSTR
and other variants. Either, I only see the first letter of the string, or I see only Y's with dots, just not the real string. Does anyone know what the real method is for creating and passing valid BSTRs from C++ to VB6?
Hopefully this will point you in the right direction. From memory...
VB6 uses COM BSTRs (2-byte wide character strings) internally, but when communicating with external DLLs it uses single- or multi-byte strings. (Probably UTF-8, but I don't remember for sure.) Your Path typedef to LPCSTR is an ANSI string, and that's why you can receive it correctly. The return value you generate is a wide-character string, but VB is expecting an ANSI string. You'll need to use WideCharToMultiByte to convert your return value before returning it.
Seems a little odd that VB does this implicit conversion, but that's the way it is. (As far as I remember.)
If you insist on using the function signature then you have to prepare a custom typelib for VB6 that includes this
[dllname("Z-FileIO.dll")]
module ZFileIO
{
[entry("FileGetParentFolder")]
BSTR FileGetParentFolder ([in] LPWSTR path);
};
In Declare
s param-types As String
are automagically converted to ANSI string, i.e. LPSTR
. The only way to pass/receive a unicode string (LPWSTR
or BSTR
) is by using typelib API function declaration.
Other than that you can always use As Long
params in the declaration and expect LPWSTR
s but then the consumer will have to wrap strings in StrPtr
on every call to the API function.
来源:https://stackoverflow.com/questions/6134666/pass-bstr-from-c-dll-function-to-vb6-application