我在Visual C ++ 1.5中创建一个DLL,以便在Visual Basic 4.0中使用(我在16位Windows 95上工作)。我创建的一个函数接收一个字符串并返回另一个字符串,参数声明为:
NPSTR CALLBACK __ export (NPSTR chain)
{
....
}
我也用LPSTR和char *测试过。
在Visual Basic中将语句作为字符串使用ByVal参数作为字符串函数但VC + +不接收链,当我运行VB程序时给出了一个错误,说明类型不匹配。
接收Visual Basic字符串并返回另一个字符串的正确声明语句是什么? 当我返回整个步骤并且没有问题。 我还想知道传递数组的方法是什么。
答案 0 :(得分:2)
除了"如何声明这样的函数"的问题,你的DLL函数的问题是它应该不从DLL返回一个字符串,除非它是指向传递的原始字符串的指针。
大多数(如果不是所有)处理字符串的Windows API函数都以这种方式执行此操作:
DLL函数的调用者负责创建字符串/缓冲区,包括在调用函数之前调整其大小。
调用者提供另一个参数,即传递的缓冲区的最大长度。
在DLL端,DLL执行如下:
DLL函数在本地字符串变量中获取它所要求的信息(这可能是一个字符数组,一个std :: string,并不重要,因为这是DLL内部的)
然后,DLL函数将此字符串信息复制到传入缓冲区,并遵循调用者给出的传入最大大小。因此,如果字符串信息实际上是1,000个字节,但是用户将100作为最大缓冲区大小,那么您只复制99(或100)个字符。
DLL函数返回复制的字符数。如果发现原始传入缓冲区很大,则调用者可以使用它将缓冲区的大小调整为实际大小(请注意,处理终止NULL是您必须在函数的调用者和DLL函数之间进行的契约,所以我在这里没有详细说明你是否应该在最后复制一个NULL。)
此外,DLL还可以返回存储整个字符串信息所需的字符总数。通常为了实现这一点,DLL函数有一个特殊的"模式"如果输出字符串为NULL,它可以工作。如果输出字符串为NULL,则DLL函数仍将获取信息,但不会将其复制到输出缓冲区,而是返回总字符数。因此调用者将对DLL函数进行两次调用,一次确定信息将有多少个字符,以便调用者相应地调整其缓冲区大小,第二次调用DLL函数将是将字符复制到缓冲。
基本上简单来说它是如何运作的。如果您的函数需要输入字符串和输出字符串,那么您的函数应该更改为:
LONG CALLBACK __ export SomeDLLFunction(NPSTR strIn, NPSTR strOut, LONG maxOutSize)
现在在VB方面:
Public Declare Function SomeDLLFunction Lib "YourDLL" (ByVal strIn As String, ByVal strOut As String, ByVal strMaxLen As Long) As Long
现在,Windows以这种方式执行操作的原因是DLL函数不再存在 返回指向本地变量的指针或引用(这是未定义的行为),不再需要弄清楚如何动态创建一个字符串(这需要一些模块来解除分配字符串,并且还确切地知道如何< / em>取消分配字符串,即要调用的函数 - 这是一个痛苦的问题。
所有东西都依赖于调用者来提供缓冲区和要写入的缓冲区的最大大小。
答案 1 :(得分:1)
以GetHostByName
函数:
// C
struct hostent* FAR gethostbyname(
_In_ const char *name
);
// VB
Public Declare Function gethostbyname
Lib "ws2_32.DLL" (ByVal host_name As String) As Long
您可以使用:
const char* CALLBACK __ export (const char* chain)
{
....
}
并在VB声明中:
// VB
Public Declare Function functionname
Lib "yourdll.DLL" (ByVal chain As String) As String