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

VC++ ATL COM 開發:SafeArray 跨語言傳遞實戰(C++ 生成、VBScript 接收)

     編輯:Java 相關知識

場景

在 VC++ (ATL) 中創建 COM 對象,實現方法返回 SAFEARRAY(VARIANT),供 VBScript / JavaScript 等腳本語言直接調用並遍歷。

關鍵點:腳本語言只能識別 VARIANT 類型的 SafeArray

因此 C++ 端必須構造 CComSafeArray<VARIANT>,而非基本類型數組。

IDL 介面定義

[id(2), helpstring("method GetArray")] 
HRESULT GetArray1([out, retval] VARIANT* v);

C++ 實現代碼 (ATL 7.1 / VC7.1)

STDMETHODIMP CATL3::GetArray1(VARIANT* pvaVariant)
{
    // 1. 準備數據源
    std::vector<float> vct;
    vct.push_back(11.4f);
    vct.push_back(12.4f);
    vct.push_back(14.4f);

    // 2. 構造 VARIANT 類型的 SafeArray
    CComSafeArray<VARIANT> saMatrix;
    for (int i = 0; i < vct.size(); ++i)
    {
        saMatrix.Add(CComVariant(vct[i])); // 每個元素包裝為 VARIANT
    }

    // 3. 返回給調用者
    VariantInit(pvaVariant);
    CComVariant var(saMatrix); // SafeArray 裝箱為 VARIANT
    var.Detach(pvaVariant);    // 所有權轉移,避免雙重釋放
    return S_OK;
}

VBScript 測試腳本

Dim v4
Set Cnxn4 = CreateObject("YourProgID.ATL3") ' 替換為實際 ProgID
v4 = Cnxn4.GetArray1()  ' 直接獲得 VBScript 數組

Dim x
For x = LBound(v4) To UBound(v4)
    MsgBox v4(x)  ' 彈出 11.4, 12.4, 14.4
Next

核心原理解析

步驟關鍵類/函數作用
數據容器std::vector<float>業務邏輯層存儲
SafeArray 構造CComSafeArray<VARIANT>ATL 封裝,自動管理記憶體、維度、邊界
元素裝箱CComVariant(value)將基本類型封裝為 VARIANT(腳本可識別)
所有權轉移CComVariant::Detach()將內部 SafeArray 指針移交給輸出參數,避免拷貝與雙重釋放
初始化輸出VariantInit()確保輸出 VARIANT 處於乾淨狀態

常見坑位與避雷指南

  • 元素類型必須是 VARIANT: CComSafeArray<float> 返回給腳會導致類型不匹配或數據解析錯誤。
  • Detach 而非 Copy: 直接轉移所有權,效率最高且語義正確。
  • 維度一致性: 腳本端 LBound/UBound 默認 1 維,C++ 端勿創建多維數組除非有特殊約定。
  • 錯誤處理: 循環中 Add 失敗會拋出異常,建議捕獲並返回 E_OUTOFMEMORY。
  • 註冊表與類工廠: 確保 COM 組件正確註冊(regsvr32),VBScript 才能 CreateObject 成功。

擴展:多維數組與不同類型

若需返回二維表格數據,可構造 CComSafeArray<VARIANT> sa(2, rows, cols),按 sa.MultiDimAdd(data, row, col) 填充。腳本端仍以 v4(row, col) 訪問(VBScript 支持多維)。

總結

ATL CComSafeArray<VARIANT> + CComVariant::Detach 是 C++ COM 組件向腳本語言高效返回數組的標準模式。掌握 VARIANT 裝箱、所有權轉移、SafeArray 邊界管理,即可實現無縫跨語言數據交換。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved