VB (VB6) 與 VC++ (Visual C++) 混合開發曾是 Windows 桌面應用主流模式。雖技術棧老舊,許多存續系統仍在運維。本文系統整理四大核心痛點:自訂類型跨語言傳遞對齊、VC 動態記憶體跨邊界使用、ActiveX 介面指標傳遞、中英混排字串長度計算,提供經實戰驗證的解決方案與程式碼範本。
VB 與 VC 結構定義對應即可,注意 32 位環境 Long (VB) = long (VC) = 4 bytes。
' VB 端
Type Person
Age As Long ' 4 bytes
Height As Double ' 8 bytes
End Type
VC 結構會在 Age 後插入 4 bytes padding 使 Height 8-byte 對齊,導致總大小 16 bytes;VB 無 padding 僅 12 bytes,傳遞時位移錯位。
' VB 端補上 4 bytes 字串
Type Person
Age As Long
Padding As String * 4 ' 佔位 4 bytes
Height As Double
End Type
// VC 端對應
struct Person {
long Age;
char Padding[4]; // 或 double dummy; 但 char[4] 更明確
double Height;
};
原則:確保每個 Double 前的成員總大小為 8 的倍數。補位成員位置必須緊鄰 Double 之前。
char* APIENTRY CreateStringBuffer(long Length) {
char* buf = (char*)malloc(Length);
return buf; // 實際回傳指標值 (32 位下相當於 long)
}
Declare Function CreateStringBuffer Lib "Test.dll" (ByVal Length As Long) As Long
Dim ptr As Long
ptr = CreateStringBuffer(20) ' 取得指標
' ... 透過 CopyMemory / RtlMoveMemory 讀寫該記憶體 ...
' 用完後必須呼叫 VC 匯出的 Free 函數歸還,否則記憶體洩漏
鐵律:誰配置誰釋放。VB 使用完畢必須呼叫 VC 提供的 FreeBuffer(ptr)。
ATL 開發 ActiveX 時,介面定義 (IDL) 若用 BSTR 會觸發 ANSI/Unicode 轉換,導致二進位結構損壞。解法:介面以 long (指標) 傳遞:
// IDL
[propget] HRESULT Student([out, retval] long* pVal);
[propput] HRESULT Student([in] long newVal);
// VB 客戶端
Dim StudentProp As Person
Dim StudentAddr As Long
StudentProp.Age = 23
StudentProp.Height = 1.78
StudentAddr = VarPtr(StudentProp) ' 取得變數位址 (需 VarPtr 函數)
AX1.Student = StudentAddr ' 傳指標
前提:ActiveX 為 In-process (DLL/OCX),同一進程空間指標有效。
VB Len() 算字元數,LenB() 算位元組數,混合字串兩者皆不準 (如 "A中國人" 顯示寬度 7)。
long APIENTRY Sizeof_vbString(char* str) {
return (long)strlen(str); // 以位元組計算,剛好等於顯示寬度 (單位:半形字元寬度)
}
Declare Function Sizeof_vbString Lib "Test.dll" (ByVal str As String) As Long
Dim len As Long
len = Sizeof_vbString("A中國人") ' 回傳 7
同樣適用純中文/純英文字串。
Double 前補位至 8 的倍數。long 傳指標,避開 BSTR 轉換。strlen 計算位元組長度。遵循上述模式,可消除 VB/VC 混合編程 90% 以上的疑難雜症。