上篇實現了基本的 DLL 調用與布爾值傳遞。本篇攻克字串跨語言傳遞難題:VB 使用 BSTR (長度前綴 + Unicode + 雙空終止),VC DLL 習慣 LPSTR (以空字元結尾的 ANSI),直接傳址會導致記憶體誤讀。關鍵在於 VB 必須用 `ByVal` 傳值,讓編譯器自動執行 BSTR→ANSI 轉換。
| 特性 | VB BSTR | C/C++ LPSTR |
|---|---|---|
| 長度資訊 | 頭部 4 字節儲存長度 | 無,靠結尾 `\0` 判斷 |
| 字元編碼 | 通常 Unicode (2 bytes/char) | ANSI (1 byte/char) 或 UTF-8 |
| 結尾標記 | 雙空字元 (`\0\0`) | 單空字元 (`\0`) |
| 指標指向 | 指向資料區第一個字元 | 指向字串第一個字元 |
extern "C" __declspec(dllexport) bool ReadString(LPCSTR lpString) {
char standard[] = "Hello World!";
return strcmp(lpString, standard) == 0;
}
Private Declare Function ReadString Lib "commication.dll" _
(ByVal send As String) As Boolean
Dim result As Boolean
Dim send As String
send = "Hello,World!"
result = ReadString(send)
' VB 自動將 BSTR 轉為 ANSI 字串指標傳入
VC 需分配 BSTR 記憶體並返回,VB 聲明為 `As String` 接收。
extern "C" __declspec(dllexport) BSTR ReadString(LPCSTR lpString) {
char standard[] = "Hello ,World!";
if (strcmp(lpString, standard) == 0)
return SysAllocString(L"Match Success"); // 分配 BSTR
else
return SysAllocString((BSTR)lpString); // 將輸入轉為 BSTR 返回
}
Private Declare Function ReadString Lib "commication.dll" _
(ByVal send As String) As String
Dim result As String
Dim send As String
send = "Hello,World!"
result = ReadString(send)
MsgBox result ' 顯示返回的字串
SysAllocString:分配 BSTR 記憶體,自動處理長度前綴與雙空終止,調用者負責 `SysFreeString` 釋放。SysStringLen / SysStringByteLen:安全獲取 BSTR 長度。WideCharToMultiByte / MultiByteToWideChar:Unicode ↔ ANSI 手動轉換,適用於非 VB 環境(如 C# P/Invoke、C++ 直接操作)。| 陷阱 | 後果 | 正確做法 |
|---|---|---|
| VB 用 `ByRef` 傳字串 | VC 讀到 BSTR 結構體而非字串內容 | 必須用 `ByVal` |
| VC 直接返回 `char*` 或 `CString` | VB 解析錯誤,甚至崩潰 | 返回 `BSTR` 並用 `SysAllocString` |
| 忘記 `SysFreeString` | 記憶體洩漏 | VB 端自動釋放;C++ 端手動釋放 |
| 字元集不匹配 (MBCS vs Unicode) | 中文亂碼 | 專案統一用 Unicode,或显式轉換 |