【问题标题】:VB6 - How to pass Strings to a DLL written in C through a .tlb FileVB6 - 如何通过 .tlb 文件将字符串传递给用 C 编写的 DLL
【发布时间】:2011-07-11 01:16:31
【问题描述】:

我正在开发一个用 VB6 编写的图形界面,我必须在其中调用某个用 C 编写的 DLL 中包含的函数。由于known limitation,我必须实现一个trick,它允许我加载它DLL 以隐式方式。

这可以创建一个 IDL 文件,使用 MIDL 编译它并在 VB6 项目中引用生成的 .tlb 文件。

问题是 VB6 字符串和 char 的 C 数组不匹配,所以我无法将它们传递(并返回)给 DLL。

C函数的原型是:

int __stdcall myFunc(char filename_in[], char filename_out[], char ErrMsg[]);

我应该在 IDL 文件中写什么以及我应该如何从 VB6 中调用它?

谢谢。

【问题讨论】:

  • 它看起来更像是一个字符数组而不是一个字符串。
  • @GolezTrol 是的,你是对的,称它们为字符串是错误的,我这样做是因为在 VB6 中我只知道字符串而不是字符数组。
  • @Beppe 如你所知,我一直在关注这个帖子。请解释为什么你不能只使用Declare Function?据我所知,除了解决 TLS 问题的 tlb 技巧之外,您还可以执行此操作。
  • @David 你的意思是我可以将Declare Function 与 tlb 技巧结合使用吗?我还没试过。我认为以这种方式声明函数会带来问题。我应该检查一下。谢谢

标签: c windows dll vb6 idl


【解决方案1】:

您必须使用 BSTR 才能使用 VB6 兼容的字符串。它是标准的 COM 字符串类型,它以 utf-16 编码存储 Unicode 字符串,就像 Win32 api 一样。

 int __stdcall myFunc(BSTR filename_in, BSTR filename_out, BSTR* ErrMsg);

您可以将 in args 直接转换为 WCHAR*,如果您需要转换为 char*,请使用 WideCharToMultiByte()(最好避免)。如果*ErrMsg 不为空,则使用 SysFreeString 在分配现有字符串之前释放它。使用 SysAllocString 分配 ErrMsg 字符串。它也必须是一个 utf-16 字符串,MultiByteToWideChar() 如果需要再次从 char* 转换。或者使用以 L 为前缀的字符串文字,例如 L"Oops"。

【讨论】:

  • @Hans 我无法更改 DLL 代码。所以我必须找到一个只涉及VB6和IDL更改的解决方案(所以我不能使用WideCharToMultiByte和SysAllocString)
  • 不确定这是否可能,而是怀疑它。 ErrMsg 参数非常有问题。为什么不编写可以更改的 C 代码,只需调用无法更改的 C 代码。
  • @Hans 这意味着要更改 DLL,我不能这样做,因为有几个应用程序/平台/服务在使用它。
  • 不,它没有。你再写一个。与您的团队成员交谈,肯定有人可以帮助您。
  • 标准 API 函数不将 BSTR 作为参数,只是普通的 LPSTR 或 LPWSTR,但仍然可以通过 Declare 或类型库调用。这与您必须使用 BSTR 才能使用 VB6 兼容的字符串 有什么关系?你的意思是 CHAR* 和 WCHAR* 参数不能被 VB6 调用?
【解决方案2】:

VB6 使用带有 ANSI 字符串参数的 stdcall 函数没有问题。只需在 IDL 中使用[in] LPSTR filename_in,运行时就会自动执行 UNICODEANSI 转换。

“魔法”也适用于 [out] 参数。

【讨论】:

    【解决方案3】:

    感谢GSergwqw 我找到了解决这个问题的方法:

    在 IDL 文件中,char 数组应该被声明为 LPSTR,所以函数的原型如下:

    int _stdcall myFunc(LPSTR file_name_in, LPSTR file_name_out, LPSTR ErrMsg)

    请注意,ErrMsg 的声明与其他数组完全相同,即使它包含输出消息(在 VB6 端可读)。

    在 VB6 方面,字符串应分配为:

    Dim file_name_in As String * 256
    Dim file_name_out As String * 256
    Dim ErrMsg As String * 256
    

    这样做,这些字符串被分配了256 的有限大小,因此与 C DLL 中的字符数组兼容。

    希望这对其他人有帮助。

    问候,

    G.B.

    【讨论】:

    • 您应该对 IDL 中的参数使用 [in][out] 提示,然后您不必设置固定长度。您正在使用正确的 SysAllocString 函数来生成 BSTR,不是吗,以便它们也获得字符串长度字集?
    • 我只尝试在 IDL 中使用 [in] [out],但没有使用 SysAllocString。我会尽快解决我遇到的其他问题。非常感谢。
    • @Beppe:这也应该在没有 * 256 部分的情况下工作。您是否尝试将字符串参数声明为 [in] LPSTR[out] LPSTR *
    • @wqw 其实我没试过,不过我也要试试这个解决方案。
    • @wqw 我试过你的解决方案,但它崩溃了,而如果我从 [out] 参数中取出指针,应用程序不会崩溃,但返回的字符串是空的。
    猜你喜欢
    • 1970-01-01
    • 2013-01-13
    • 2010-12-15
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    相关资源
    最近更新 更多