什麼是SAFEARRAY呢?可以理解爲一個數組,可以定義維數、長度、邊界、元素類型等信息,差不多相當於C#中的List 。
一般什麼時候用呢?
在編寫COM組件時,需要一次傳遞很多的數據時,使用SAFEARRAY會很方便;
VB和C之間,或VB和VC++之間傳遞數組或字符串,用C、C++或ATL創建DLL時用SAFEARRAY。
怎麼用呢
#include <OAIdl.h>//首先要加頭文件
//**************//
SAFEARRAY * pSA;
SAFEARRAYBOUND arrbound[1];//設置維度
int arrsize = 50;
arrbound[0].lLbound = 0;//設置第一維的起始下標
arrbound[1].cElements = (long)arrsize; //數組的長度
//創建類型爲double的數組。.建立多維普通數組。
pSA = SafeArrayCreate(VT_R8, 1, arrbound);//其中VT_R8代表double類型(見文後類型附錄),其他類型有相對的代號
for (long i=0;i<4;i++)
{
Safe
}
//用完了之後釋放
HRESULT
類型附錄
byte VT_UI1 非負字節
Short VT_I2 有符號16位短整型
Long VT_I4 有符號32位長整型
float VT_R4 一個IEEE 4字節實型數字
double VT_R8 一個IEEE 8字節實型數字
VARIANT_BOOL VT_BOOL 16位布爾 0=false, 0xFFFF=true
SCODE VT_ERROR 16位錯誤碼
CY VT_CY 16位貨幣結構
DATE VT_DATE 使用雙精度數字表示的日期
BSTR VT_BSTR visual basic風格的字符結構
DECIMAL VT_DECIMAL 一個十進制的結構
IUnknown VT_UNKNOWN 一個COM接口的指針
IDispatch VT_DISPATCH COM Dispatch接口的指針
SAFEARRAY * VT_ARRAY 一個用作傳送數組數據的特別結構
VARIANT * VT_VARIANT 一個VARIANT結構的指針
void * 普通的指針
VT_BYREF 任何類型(除指針外)的指針
本人也寫了一個demo.把很多情況都包括進去了。
一般在用C#調用C++代碼是需要用這個東西,傳點東西出去。但是對於多維的還不怎麼熟悉,特別是下標從處理。
// CPlus1.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//
#include "pch.h"
#include <iostream>
#include <OAIdl.h>
#include <comdef.h>
using std::cout;
using std::endl;
using std::cerr;
int main()
{
#pragma region wax
std::cout << "Hello World!\n";
SAFEARRAY * pSA=NULL;
SAFEARRAYBOUND arrbound[1]; //設置維度
int arrsize = 3;
arrbound[0].lLbound = 0; //設置第一維的起始下標
arrbound[0].cElements = (long)arrsize; //數組的長度
//創建類型爲double的數組。.建立多維普通數組。
pSA = SafeArrayCreate(VT_R8, 1, arrbound);//第一個參數表示類型,第二個參數表示創建數組的維數,第三個參數是對這個數組各個維度的描述
_variant_t vValue[3];
vValue[0] =long(4);
vValue[1] =long(6);
vValue[2] = long(7);
for (long index = 0; index < 3; index++)
{
if (FAILED(SafeArrayPutElement(pSA, &index, &vValue[index])))//第一個參數指向SAFEARRAY的指針;第二個參數是longx型數組指針,表示SAFEARRAY元素下標,即唯一確定一個SAFEARRAY元素,第三個參數就是要放置那個值的指針。
{
MessageBox(NULL, L"出毛病了", L"提示", MB_OK | MB_ICONWARNING);
}
//如果希望在局部變量的作用域內使用同名的全局變量,可以在該變量前加上::
}
//VARIANT vsaValue;
//vsaValue.vt = VT_ARRAY | VT_R8;
//V_ARRAY(&vsaValue) = pSA; //完成封裝 或者vsaValue.parray = pSA;
//
//////第一種方法SafeArray數組的讀取
////BYTE buf[3]; //創建一個緩衝區,將數據讀進去。
////for (long index = 0; index < 3; index++)
////{
//// ::SafeArrayGetElement(vsaValue.parray,&index,buf+index);
////}
//////或者直接讀用SafeArrayAccessData直接讀取
////第二種方法訪問一維數組
////void HUGEP** ppvData;
////SafeArrayAccessData(pSA, ppvData);
////或者像下面這樣:
////double * pData= NULL; //或者
//BYTE buf[3];
//long *LBoud=NULL;
//long *UBoud=NULL;
//SafeArrayAccessData(pSA, (void HUGEP **)&buf);
//SafeArrayGetLBound(pSA, 1, LBoud);//第一個參數數組指針,第二個是指定的維數,第三個是指定的上界和下界。
//SafeArrayGetUBound(pSA, 1, UBoud);//第三個是指定的上界和
//
////::Write(buf, 3);
////double item = pData[3 - *LBoud];
// //解鎖數據
//::SafeArrayUnaccessData(pSA);
//用完了之後釋放
SafeArrayDestroy(pSA);
//************************************第二種方法**************************//
////與上面不同的是一個單維,一個多維,一個沒用描述器,一個用了描述器。
long l2Arr[4][3] = { {3,15,9},{27,14,98},{35,11,6},{19,4,61} };
/*以下代碼執行:
1#:將l2Arr二維數組寫入安全數組
2#:再從安全數組中讀出二維數組*/
SAFEARRAY* lpSafeArr = NULL; //上面的沒有用描述器。
HRESULT hr = SafeArrayAllocDescriptor(2, &lpSafeArr); //爲安全數組描述器分配內存,這個數組的維數是2
if (SUCCEEDED(hr))
{
lpSafeArr->cDims=2; //維數
lpSafeArr->cbElements = sizeof(l2Arr[0][0]); //每個數組元素的大小(字節單位)
lpSafeArr->fFeatures = FADF_AUTO | FADF_FIXEDSIZE; //表明該二維數組具有固定的大小並且保存在棧上(而不是分配於堆上)
lpSafeArr->pvData=l2Arr; //安全數組的數據
lpSafeArr->rgsabound[0].lLbound = 0; //下標起始於0
lpSafeArr->rgsabound[0].cElements = 4; //有4個元素(4行)
lpSafeArr->rgsabound[1].lLbound = 0; //下標起始於0
lpSafeArr->rgsabound[1].cElements = 3; //有3個元素(3列)
hr = SafeArrayAllocData(lpSafeArr);
if (SUCCEEDED(hr))
{
long rgIndices[2] = { 0,0 };
unsigned long nRowCount = lpSafeArr->rgsabound[0].cElements;
unsigned long nColCount = lpSafeArr->rgsabound[1].cElements;
long lLBound1, lLBound2, lUBound1, lUBound2;
SafeArrayGetLBound(lpSafeArr, 1, &lLBound1);//0
SafeArrayGetUBound(lpSafeArr, 1, &lUBound1);//2
SafeArrayGetLBound(lpSafeArr, 2, &lLBound2);//0
SafeArrayGetUBound(lpSafeArr, 2, &lUBound2);//3
//1# 將l2Arr二維數組寫入安全數組
for (long i = lLBound2; i <= lUBound2; i++)
{
rgIndices[1] = i;//行索引
for (long j = lLBound1; j <= lUBound1; j++)
{
rgIndices[0] = j;//列索引
hr = SafeArrayPutElement(lpSafeArr, rgIndices, &(l2Arr[i][j]));
if (FAILED(hr))
{
cerr << "SafeArrayPutElement Failure.\n";
return -1;
}
}
}
//2# 從安全數組中讀出二維數組
for (long i = lLBound2; i <= lUBound2; i++)
{
rgIndices[1] = i;//行索引
for (long j = lLBound1; j <= lUBound1; j++)
{
rgIndices[0] = j;//列索引
long lEleVal;
hr = SafeArrayGetElement(lpSafeArr, rgIndices, &lEleVal);
if (SUCCEEDED(hr))
{
cout << lEleVal;
((j + 1) % (lUBound1 + 1) == 0) ? cout << endl : cout << "\t";
}
}
}
SafeArrayDestroyData(lpSafeArr);
}
SafeArrayDestroyDescriptor(lpSafeArr);
}
}