[英]How to return a string of unknown size from DLL to Visual Basic
我有一个可视化的基本脚本,该脚本调用执行网络请求的DLL并以字符串形式返回一个请求的结果。 调用DLL之前,结果的长度未知。 DLL由我自己用C / C ++编写。
据我所知,从DLL返回字符串的最常用方法是将预分配的字符串对象的引用作为对DLL的争论。 然后,DLL函数将返回的字符串填充到此内存中。 问题在于分配的缓冲区必须足够大,以确保结果适合该缓冲区。
是否可以直接从DLL返回结果字符串? 还是有其他方法根据结果的长度动态分配字符串对象并将其返回给VB调用者?
我尝试了不同的方法,例如像这样(丑陋的示例):
__declspec(dllexport) const char* sendCommand(const char* cmd, const char* ipAddress)
{
// do request stuff...
long lengthOfResult = ...
const char* result = new char[lengthOfResult];
return result;
}
或喜欢..
__declspec(dllexport) BSTR sendCommand(const char* cmd, const char* ipAddress)
{
_bstr_t result("Test string.");
BSTR bstrResult = result.copy();
return bstrResult;
}
视觉基本方面:
Declare Function sendCommand Lib "magicdll.dll" (cmd as String, ip as String) As String
result = sendCommand("any command", "192.168.1.1")
两者都没有成功-VB中的结果字符串充满了垃圾。
大多数DLL不返回字符串。 他们接受一个字符串作为参数,并将一个char数组复制到该缓冲区中。 尝试这样的事情:
_declspec(dllexport) int sendCommand(const char* cmd,
const char* ipAddress,
char* pszBuffer,
int nBufferSize)
然后将您的字符串复制到该缓冲区中并返回字符数:
int nSize = nBufferSize;
if (lstrlen(szMyResult) < nBufferSize)
nSize = lstrlen(szMyResult);
lstrcpyn(pszBuffer, szMyResult, nSize);
return nSize;
从VB调用时,分配一个字符串并指定其大小:
Dim s As String, intChars As Long
s = Space$(128)
intChars = sendCommand("...", "...", s, Len(s))
s = Left$(s, intChars)
编辑:
如果必须通过函数调用返回字符串,则可以尝试创建BSTR(VB样式的字符串)并返回它。 您需要将字符串转换为Unicode,然后使用SysAllocString()
创建BSTR。 例如:
BSTR ReturnVBString()
{
return SysAllocString(L"This string is from a C DLL.");
}
加入对话较晚,但是...
最初的问题询问如何处理可变的缓冲区大小。 我相信做到这一点的唯一方法是通过两个函数调用。 一个获取缓冲区大小,然后另一个获取字符串。
我正在使用类似的技术来使用C ++函数以访问形式获取加密字符串。 VBA看起来与此类似(细节省略):
Private Declare Function DllAes_ComputeCipher _
Lib "c:\RTScada\bin\ObjProc.dll" _
Alias "Aes_ComputeCipher" (ByRef sKey As String, ByRef sStr As String) As Integer
Private Declare Function DllAes_GetCipher _
Lib "c:\RTScada\bin\ObjProc.dll" _
Alias "Aes_GetCipher" (ByVal sEncode As Long) As Boolean
Private Sub CipherString_LostFocus()
.
.
.
iSize = DllAes_ComputeCipher(sKey, sString)
sEncoded = Space(iSize)
bSuccess = DllAes_GetCipher(StrPtr(sEncoded))
End Sub
并去除了某些C ++函数(实际函数确实比这重得多-但您应该明白这一点)
// Define a global string - in reality this is computed by the ComputeCipher function
char* gpStr = "we are the dreamers of dreams and we are the music makers";
#define CLASS_DECLSPEC extern "C" __declspec(dllexport)
//========================================================================
CLASS_DECLSPEC int __stdcall Aes_ComputeCipher(const char* pKey, const char* pStr)
{
return strlen(gpStr);
}
//========================================================================
CLASS_DECLSPEC bool __stdcall Aes_GetCipher(LPSTR pReturn)
{
char pStr = gpStr;
int iLen = strlen(pStr);
int idx;
for (idx = 0; idx < iLen; idx++) {
*pReturn = *pStr;
pReturn += 2;
pStr++;
}
return true;
}
你的旅费可能会改变...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.