在 VC++ (ATL) 中創建 COM 對象,實現方法返回 SAFEARRAY(VARIANT),供 VBScript / JavaScript 等腳本語言直接調用並遍歷。
因此 C++ 端必須構造 CComSafeArray<VARIANT>,而非基本類型數組。
[id(2), helpstring("method GetArray")]
HRESULT GetArray1([out, retval] VARIANT* v);
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;
}
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 處於乾淨狀態 |
CComSafeArray<float> 返回給腳會導致類型不匹配或數據解析錯誤。LBound/UBound 默認 1 維,C++ 端勿創建多維數組除非有特殊約定。Add 失敗會拋出異常,建議捕獲並返回 E_OUTOFMEMORY。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 邊界管理,即可實現無縫跨語言數據交換。