什么是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);
}
}