如何将VB字符串参数传递给用C编写的函数?

时间:2012-08-03 13:48:44

标签: visual-c++ vb6

我有一个问题:我正在尝试将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;
}

2 个答案:

答案 0 :(得分:3)

自从我编写VB / Win32函数声明以来,它已经很久了,但我很确定我记得默认情况下,VB6中外部库函数的所有参数都是通过参数传递的。但是,VB6 String类型已经是基于指针的类型,因此已经通过参数传递的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)

答案 1 :(得分:2)

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

您的代码使用LPSTR *,它是指向每个字符ANSI字符串1个字节的指针。显然,您这样做是为了将您的字符串返回到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 *,您必须在类型库中声明您的功能 - 我没有时间在这里讨论。