我有一个问题:我正在尝试将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;
}
答案 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 *,您必须在类型库中声明您的功能 - 我没有时间在这里讨论。