簡體   English   中英

如何從DLL返回未知大小的字符串到Visual Basic

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM