从 C++ 传递 BSTR DLL 函数到 VB6 应用程序

发布于 2024-11-09 15:53:36 字数 790 浏览 0 评论 0原文

我的 VB6 应用程序中有以下代码:

Private Declare Function FileGetParentFolder Lib "Z-FileIO.dll" _
(ByVal path As String) As String

Output.AddItem FileGetParentFolder(FileText.Text)

输出是一个列表,FileText 是一个包含文件路径的文本字段。我的 C++ DLL 包含此函数:

extern "C" BSTR ZFILEIO_API FileGetParentFolder(Path p)
{
    try {
        return SysAllocString(boost::filesystem::path(p).parent_path().c_str());
    } catch (...) {
        return SysAllocString(L"");
    }
}

其中 Path 的类型定义为 LPCSTR。该参数完美地进入我的 DLL,但无论我尝试传回什么,VB6 应用程序都只显示垃圾。我使用 SysAllocStringByteLength 尝试了几种不同的方法,将 SysAllocString 参数转换为 LPCWSTR 和其他变体。要么我只看到字符串的第一个字母,要么我只看到带点的 Y,而不是真正的字符串。有谁知道创建有效 BSTR 并将其从 C++ 传递到 VB6 的真正方法是什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

盛夏已如深秋| 2024-11-16 15:53:36

希望这将为您指明正确的方向。根据记忆...

VB6 在内部使用 COM BSTR(2 字节宽字符串),但在与外部 DLL 通信时,它使用单字节或多字节字符串。 (可能是 UTF-8,但我不太记得了。)您的 LPCSTR 的 Path typedef 是一个 ANSI 字符串,这就是您可以正确接收它的原因。您生成的返回值是一个宽字符字符串,但 VB 需要一个 ANSI 字符串。在返回之前,您需要使用 WideCharToMultiByte 来转换返回值。

VB 执行这种隐式转换似乎有点奇怪,但事实就是如此。 (据我所知。)

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.)

一身骄傲 2024-11-16 15:53:36

如果您坚持使用函数签名,那么您必须为 VB6 准备一个自定义类型库,其中包含此

[dllname("Z-FileIO.dll")]
module ZFileIO
{
    [entry("FileGetParentFolder")]
    BSTR FileGetParentFolder ([in] LPWSTR path);
};

Declare 的参数类型 As String 中自动转换为 ANSI 字符串,即LPSTR。传递/接收 unicode 字符串(LPWSTRBSTR)的唯一方法是使用 typelib API 函数声明。

除此之外,您始终可以在声明中使用 As Long 参数并期望 LPWSTR ,但消费者必须将字符串包装在 StrPtr 中每次调用 API 函数。

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 Declares 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 LPWSTRs but then the consumer will have to wrap strings in StrPtr on every call to the API function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文