首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

COM 常用資料類型轉換全攻略:BSTR、_bstr_t、CComBSTR、VARIANT、_variant_t、SAFEARRAY

     編輯:關於C語言

COM 開發中最讓人頭痛的莫過於各種字串、變體與陣列類型的相互轉換。本文系統整理 BSTR 族、VARIANT 族、SAFEARRAY 的定義、記憶體管理規則、封裝類別用法與常見陷阱,附程式碼範例。

BSTR 家族

本質定義

typedef OLECHAR *BSTR;   // OLECHAR = WCHAR = wchar_t
// 記憶體佈局:前 4 位元組 = 字串位元組長度(不含結尾 null),後接 Unicode 字元陣列,雙 null 結尾

API 快查表

函式用途
SysAllocString配置 BSTR 並複製內容
SysReAllocString重新配置並複製
SysAllocStringLen指定長度配置
SysFreeString釋放 BSTR
SysStringLen取得字元數
SysStringByteLen取得位元組長度(前綴值)

_bstr_t 封裝(推薦日常使用)

  • 自動管理參考計數與記憶體,支援複製語意。
  • 關鍵方法:Detach() 釋放擁有權、Attach() 取得擁有權、Assign() 複製內容、GetAddress() 取得指標供輸出參數填寫。
  • 範例見原文 MSDN Demo,核心觀念:儘早將介面傳入的 BSTR 轉為 _bstr_t 操作,輸出前再轉回 BSTR。

CComBSTR 封裝(ATL)

  • 功能類似 _bstr_t,但介面較底層,陷阱較多(如複製語意、附加/分離邏輯),非 ATL 專案建議優先用 _bstr_t。

VARIANT / _variant_t

VARIANT 結構

  • vt 欄位指示聯合體中有效欄位類型(VT_I4、VT_BSTR、VT_ARRAY、VT_DISPATCH 等)。
  • 必須 VariantInit() 初始化,用畢 VariantClear() 釋放。

六大注意事項

  1. 數值類型(VT_I2、VT_I4 等)直接儲存於結構,型別改變會導致指標失效。
  2. VT_BYREF 僅持有指標,記憶體由呼叫者管理。
  3. VT_BSTR 需 SysAllocString/SysFreeString 配對。
  4. VT_ARRAY 需 SafeArrayCreate/SafeArrayDestroy 配對。
  5. VT_DISPATCH/VT_UNKNOWN 需手動 AddRef/Release。
  6. 結構體嵌入需自訂 GUID 與 IRecordInfo。

_variant_t 封裝

  • 自動管理 VariantInit/Clear、記憶體、參考計數,介面簡潔,建議優先使用。

SAFEARRAY 完整操作指南

建立方式

  1. 棧上建立:SafeArrayAllocDescriptor + 手動設定 bounds + pvData 指向現有陣列。
  2. 堆上一維:SafeArrayAllocDescriptor + SafeArrayAllocData + SafeArrayAccessData 寫入。
  3. 堆上二維:同上,注意 列主序:lDimension[1]=row, [0]=col。
  4. 一鍵建立:SafeArrayCreate(VT_I4, 1, &bound) / SafeArrayCreate(VT_I4, 2, bounds)。
  5. 自訂結構陣列:SafeArrayCreateEx + IRecordInfo。

存取方式

  • SafeArrayAccessData 取得直接指標(高效,需成對 UnaccessData)。
  • SafeArrayGetElement/PutElement 逐元素存取(安全,支援多維)。

最佳實踐原則

  1. 介面層使用 BSTR/VARIANT/SAFEARRAY(IDL 規定)。
  2. 內部實作立即轉為 _bstr_t/_variant_t/CComSafeArray 操作。
  3. 輸出前再轉回原生類型,嚴禁在內部邏輯直接操作裸指標。
  4. 所有配置/釋放成對出現,善用 RAII 封裝類別自動管理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved