2

我这里有一个问题:我正在尝试将 VB6 字符串传递给用 C 编写的函数,但我认为它与 LPSTR 不同。调用该函数时,我的 VB6 IDE 崩溃。如何将 VB 字符串作为参数传递给 C 中的函数?下面是我的代码。谢谢大家:

VB6

Private Declare Function WritestStr Lib “teststr.dll” (ByRef mystr As String) As Long

Private Sub command1_Click()

    Dim mystr as string

    Call WritestStr(mystr)
    Msgbox mystr

End Sub

VC6

include “windows.h”

Int __stdcall WritestStr(LPSTR *mystr)
{
    *mystr = “Venancio Guedes”;
    return 0;
}
4

2 回答 2

3

自从我编写 VB/Win32 函数声明以来已经很久了,但我很确定我记得默认情况下,VB6 中外部库函数的所有参数都是通过引用传递的;但是,VB6 String 类型已经是基于指针的类型,因此已经通过 byref 传递的 byref 参数会将错误的值压入堆栈。这会导致引用在 DLL 内崩溃。尝试将它传递给 ByVal,因为参数的“值”实际上是字符串指针本身,这是 DLL 函数所期望的。

正如我所说,自从我编写这些声明以来已经很长时间了,所以所有标准的警告都适用,但我很确定这很接近。

祝你好运!

编辑DLL 函数的 ByVal 声明是正确的。现在的修复应该是让您在使用空格调用 DLL 函数之前初始化/分配字符串,例如:

Dim vbString as String
Dim result as Long
vbString = Space$(255) ' just make sure this number is large enough
result = WritestStr(vbString)
于 2012-08-03T13:55:40.923 回答
2

VB 字符串在 OLE 文档中称为 BSTR,并且几乎与 LPWSTR 兼容。它们是每个字符 2 个字节的 Unicode (UTF-16) 字符串,但在字符串指针指向的内存之前的长度为 32 位。

您的代码使用 LPSTR*,它是一个指向每个字符 1 个字节的 ANSI 字符串的指针。显然,您这样做是为了将您的字符串返回到 VB6 代码。

不幸的是,这两者是不相容的。

代码崩溃的原因是您将 VB6 变量 <mystr> 传递给您的函数,但默认情况下它设置为 vbNullString,类似于:

BSTR mystr = NULL;

但是你的主要问题是VB不可能使用你写的C函数。无法为 LPSTR* 编写 Declare 语句。如果您将 C 代码更改为

include “windows.h”

Int __stdcall WritestStr(LPSTR mystr)
{
    const LPSTR myconststr = “Venancio Guedes”;

    if (mystr)
        int destlen = strlen(mystr);
        int srclen = strlen(myconststr);
        if (destlen >= srclen)
        {
            strcpy(mystr, myconststr);
            return 0;
        }
    return srclen;
}

...您可以将声明更改为:

Private Declare Function WritestStr Lib “teststr.dll” (ByVal mystr As String) As Long

...并确保您声明一个缓冲区以接受该字符串。您可以为 LPSTR 编写 Declare 语句,但您需要

Private Sub command1_Click()

    Dim mystr As string
    Dim nLen As Long

    mystr = Space$(1024)
    nLen = WritestStr(mystr)

    Msgbox Left$(mystr, nLen)

End Sub

这让人想起大多数 Win32 API 函数的工作方式。

将 mystr 作为 ByVal 传递通知 VB6 它必须将 <mystr> 从 BSTR 复制到临时 LPSTR,并将指针传递给该缓冲区。当它执行完 WriteStr() 后,它会将 LPSTR 缓冲区复制回原来的 BSTR。

分配一个 VB 字符串缓冲区 <mystr> 以传递给您的函数可以让您回写一些东西。

或者,您可以重写您的 C 程序以本机接受 BSTR(如果您想拥有多语言,这是最干净和更便携的解决方案)。在这种情况下,您的原始 VB6 声明将保留,即 ByRef mystr As String。不幸的是,您仍然必须像在这里所做的那样写入缓冲区。

如果你想拥有 LPWSTR*、LPSTR* 或 BSTR*,你必须在类型库中声明你的函数——我没有时间在这里讨论。

于 2012-08-03T18:16:27.390 回答