SegeX SgxVariantArrayT:VC封装支持多维数组的变体类型(VRIANT 、SafeArray)(附免费免积分源代码)
----哆啦刘小洋 原创,转载需说明出处 2023-01-04
SgxVariantArrayT:支持多维数组的变体类型
- 1 简介
- 2 方法原理
- 2.1 继承于_variant_t
- 2.2 模板类型到VARIANT VT的转换
- 3 主要方法(接口)
- 4 与CArray、vector数组的转换
- 5 Automation中的应用实例
1 简介
VRIANT变体类型是Com技术中的一种标准数据类型,Vb中的变体也是这种类型,在针对Com编程过程中,比如AutoCAD、Surfer、Excel、Word中使用自动化Automation(OLE)功能时,经常遇到VARIANT数组的情况,在VC中使用VARIANT数组很繁琐,特别是多维数组。本文介绍了一种封装VARIANT数组的方法并附带了完整的免费代码,具备以下主要功能:1)最多4维数组的支持;2)使用VARIANT数组类似于CArray、vector,也类似与Vb中的动态数组;3)支持CArray、vector与VARIANT的转换(1~4维)。本文的代码基于VC2012及以上(将代码中的">>"中间留个空格,也可以用于vc6)。
2 方法原理
其实没有什么原理,就是把VC中繁琐的SafeArray申明、赋值、设置都封装到一个VAIRANT继承类中。采用模版类,是为了读取和写入数组数据书写更方便。主要关键点就两个:
2.1 继承于_variant_t
如下:
template <class T>
class CSgxVariantArrayT : public _variant_t
{//没有成员变量,保持和VARIANT最大的兼容。
};
2.2 模板类型到VARIANT VT的转换
VARIANT是一种标准数据格式,因此只能对应有限的常用数据类型。常用的VT类型和c语言类型对照关系如下:
VT_R8 -> double
VT_R4 -> float
VT_I4 / VT_INT -> int / long
VT_BSTR -> BSTR
VT_I1 -> char
VT_I2 -> short
因此在构造时根据模板参数来获取对应的vt值,代码如下:
template <class T>
class CSgxVariantArrayT : public _variant_t
{//...void CalcVT(){if (typeid(T) == typeid(double))vt = VT_R8;else if (typeid(T) == typeid(int))vt = VT_I4;else if (typeid(T) == typeid(UINT))vt = VT_UI4;else if (typeid(T) == typeid(float))vt = VT_R4;else if (typeid(T) == typeid(char))vt = VT_I1;else if (typeid(T) == typeid(UCHAR))vt = VT_UI1;else if (typeid(T) == typeid(BOOL))vt = VT_I4;else if (typeid(T) == typeid(short))vt = VT_I2;else if (typeid(T) == typeid(unsigned short))vt = VT_UI2;else if (typeid(T) == typeid(bool))vt = VT_BOOL;else if (typeid(T) == typeid(BSTR))vt = VT_BSTR;else if (typeid(T) == typeid(__int64))vt = VT_I8;else{ASSERT(FALSE);throw ("data type not supported");}vt |= VT_ARRAY;}
};
3 主要方法(接口)
template <class T>
class CSgxVariantArrayT : public _variant_t
{public://构造CSgxVariantArrayT(void);CSgxVariantArrayT(ULONG nCount, T* pData = NULL);CSgxVariantArrayT(const VARIANT& v);//获取某一维的元素个数long GetSize(long nDim);//设置数组大小BOOL Redim(long n1);BOOL Redim(long n1, long n2);BOOL Redim(long n1, long n2, long n3);BOOL Redim(long n1, long n2, long n3, long n4);//获取数组元素(读写)T& operator()(long n1);T& operator()(long n1, long n2);T& operator()(long n1, long n2, long n3);T& operator()(long n1, long n2, long n3, long n4); //写数组元素(另一种写方案,用于数组转换)HRESULT SetAt(long nIndex, variant_t v);HRESULT SetAt(long n1, long n2, variant_t v);HRESULT SetAt(long n1, long n2, long n3, variant_t v);HRESULT SetAt(long n1, long n2, long n3, long n4, variant_t v);
};
最多支持到4维数组。实现都是利用Windows系统函数SafeArrayRedim、SafeArrayCreate、SafeArrayDestroy等,一句一句把他们封装起来。另外,采用了重载()的方式,很遗憾,多维数组无法采用重载[]的方式提供类似 arr[][][] 读取数据的方法。
想了解具体实现,请参见文末附带的源代码。
使用方法的示例代码如下:
#include "SgxVariantArrayT.h"void test()
{CSgxVariantArrayT<double> darr(5); //申明一个变体数组,初始化5个元素darr(0) = 1.0;darr(4) = 5.0;//读取索引[4]位置的数据darr.Redim(2, 3);//变成二维数组darr(0, 0) = 1.0;darr(0, 1) = 2.0;//读取索引[0][1]位置的数据double d = darr(0, 1);
}
特别的,VARIANT支持的字符串为BSTR类型,因此使用时要注意:
#include "SgxVariantArrayT.h"
#include <afxtempl.h> //for CString
#include <string> //for std::stringvoid test_str()
{CSgxVariantArrayT<BSTR> sarr(5); //必须为BSTRsarr(0) = bstr_t("xx").copy();//注意这里要用.copy()得到一个新的bstr_t实例,否则临时对象会共用一个实例,导致数组赋值后只能得到一个相同的值CString s("yy"), s1;sarr(4) = bstr_t(s).copy();//用CString 赋值s1 = sarr(0);//赋值给CStringstd::string ss("ss"), ss1;sarr(2) = bstr_t(ss.c_str()).copy();//用std::string 赋值ss1 = bstr_t(sarr(2));//赋值给std::string
}
4 与CArray、vector数组的转换
支持MFC CArray、std::vector数组以及一维指针数组。
# define CArray1T CArray<T, T>
# define CArray2T CArray<CArray<T, T>>
# define vector1T std::vector<T>
# define vector2T std::vector<std::vector<T>>
//...template <class T>
class CSgxVariantArrayT : public _variant_t
{//一维指针数组互换BOOL From(T* arr, int n1);BOOL ToArray(T* arr, int n1);//MFC CArray数组互换BOOL From(CArray1T& arr);BOOL From(CArray2T& arr);...BOOL ToArray(CArray1T& arr);BOOL ToArray(CArray2T& arr);...//std::vector数组互换BOOL From(vector1T& arr); BOOL From(vector2T& arr);...BOOL ToArray(vector1T& arr);BOOL ToArray(vector2T& arr);};
对CString std::string数组的转化必须要做特殊处理。略过。感兴趣可查看源代码FromStringArray,ToStringArray函数。
示例代码:
#include "SgxVariantArrayT.h"
void test_SgxVariantArrayT()
{long i, j, k, m, nn;//test with CArray{//一维CSgxVariantArrayT<double> vd;CArray<double, double> ad;ad.SetSize(6);for (i = 0; i < 6; ++i)ad[i] = i;vd.From(ad);vd.ToArray(ad);//二维nn = 0;CArray2(double) ad2;CSgxVariantArrayT<double>::SetArraySize(ad2, 2, 3);for (j = 0; j < 3; ++j)for (i = 0; i < 2; ++i)ad2[i][j] = nn++;vd.From(ad2);vd.ToArray(ad2);} //test with CStringArray{CStringArray as;CSgxVariantArrayT<BSTR> sv;as.SetSize(6);for (i = 0; i < 6; ++i)as[i].Format(_T("%d"), i * 10);sv.FromStringArray(as);sv(0) = bstr_t(as[1]).copy();//important with copy(), or sv(0) = sv(1)sv(1) = bstr_t(as[0]).copy();sv.ToStringArray(as);}//test with vector{//一维CSgxVariantArrayT<double> vd;vector1(double) ad;ad.resize(6);for (i = 0; i < 6; ++i)ad[i] = i;vd.From(ad);vd.ToArray(ad);//二维nn = 0;vector2(double) ad2;CSgxVariantArrayT<double>::SetArraySize(ad2, 2, 3);for (j = 0; j < 3; ++j)for (i = 0; i < 2; ++i)ad2[i][j] = nn++;vd.From(ad2);vd.ToArray(ad2);}//test with std::string Array{std::vector<std::string> as;char* cs[] = { "a", "b" , "c" , "d" , "e" , "f" };CSgxVariantArrayT<BSTR> sv;as.resize(6);for (i = 0; i < 6; ++i)as[i] = cs[i];sv.FromStringArray(as);sv(0) = bstr_t("xxx").copy();//important with copy(), or sv(0) = sv(1)sv(1) = bstr_t("yyy").copy();sv.ToStringArray(as);}
}
5 Automation中的应用实例
比如VC调用AutoCAD自动化:
#import "acax20chs.tlb" no_namespace named_guids
#include "SgxVariantArrayT.h"void OnTest_Interface_vc2022()
{CoInitialize(NULL);IAcadApplicationPtr pApp;IAcadDocumentsPtr pDocs;IAcadDocumentPtr pDoc;IAcadModelSpacePtr pMs;HRESULT h = NOERROR;CLSID clsid;//获取Class IDh = ::CLSIDFromProgID(OLESTR("AutoCad.Application"), &clsid);if (FAILED(h))return;//获取正在运行的对象h = pApp.GetActiveObject(clsid);if (!SUCCEEDED(h)){//没有正在运行的对象,就创建一个h = pApp.CreateInstance(clsid, NULL, CLSCTX_ALL);if (FAILED(h))return;}pApp->WindowState = AcWindowState::acMax;pApp->Visible = VARIANT_TRUE;//新建一个AutoCAD文档pApp->get_Documents(&pDocs);pDoc = pDocs->Add();//模型空间pDoc->get_ModelSpace(&pMs);//添加一条多义线CSgxVariantArrayT<double> arr(6);arr(0) = 0.0; arr(1) = 0.0; arr(2) = 0.0;arr(3) = 10.0; arr(4) = 10.0; arr(5) = 0.0;pMs->AddPolyline(arr);pApp->ZoomAll();
}
下载源代码。(免费、免积分)。源代码测试请调用静态函数 CSgxVariantArrayT::test()。
#include "SgxVariantArrayT.h"
void test()
{CSgxVariantArrayT<int>::test();
}
如果你觉得有帮助,别忘了帮我点个关注或点个赞!
SegeX SgxVariantArrayT:VC封装支持多维数组的变体类型(VRIANT 、SafeArray)(附免费免积分源代码)相关推荐
- 根据数组中的某个键值大小进行排序,仅支持二维数组
/** * 根据数组中的某个键值大小进行排序,仅支持二维数组 * * @param array $array 排序数组 * @param string $key 键值 ...
- Matlab常见报错:错误使用 conv2不支持 N 维数组;cell类型数组不支持运算符
一.错误使用 conv2不支持 N 维数组: 错误样例: 原因:提示错误使用 conv2不支持 N 维数组,可能是因为你读取的图像并不是灰度图像,而是RGB图像,有red/green/blue三种颜色 ...
- 【HDU】1251统计难题 (字典树:二维数组,结构体数组,链表,map)
使用二维数组或者结构体数组都可以,但是在计数的时候有一点点小区别 一.结构体数组 #include <cstdio> #include <cstring> #include & ...
- NEFU 大一寒假培训【一】二维数组、结构体
主题:二维数组.结构体 A 二维矩阵对角线和 Description 计算m×m的方阵的对角线所有元素的和 Input 输入数据有多组,每组第1行为m (2<=m<=10),接下来有m行m ...
- acm新手小白必看系列之(1)——二维数组及结构体精讲附带例题
*acm新手小白必看系列之(1)--二维数组及结构体 ** c++准备工作** (可能小白像我一样也是学习的c语言) 万能头文件,放在第一行 #include<bits/stdc++.h> ...
- php variant 数组,php – 如何将8209数组对象变体转换为VT_VARIANT
我正在调用一个COM对象方法,该方法在我的PHP代码中返回8209类型的数组变量对象. $com_VArray = $com_Object->objectMethod; //Is a 8209 ...
- matlab多维数组、结构体数组
1.多维数组 第三维称为页,需要注意的是每一页存放的二维数组维度要一致,也就是行列数要一致... 1 2 3 4 5 6 7 a=[1,2; 3,4]; b=[2,2; 5,6]; A ...
- C语言一维数组、二维数组、结构体的初始化
C语言数组的初始化表示方法 一.C语言一维数组初始化: (1)在定义数组时对数组元素赋以初值.如: static int a[10]={0,1,2,3,4,5,6,7,8,9}; 经过上面的定义和初始 ...
- C语言动态二维数组,结构体动态申请内存空间
在C语言中,申请一般数组时,数组大小必须是常量.即使是赋了特定值的变量,也不行,比如:int n=3;int a[3];这样的做法是错误的,我们需要动态申请数组内存,如下申请一个动态整数(int)二维 ...
最新文章
- JavaScript递归应用与实践
- 【NOIP2017模拟6.25】小W的动漫
- Hadoop! | 大数据百科 | 数据观 | 中国大数据产业观察_大数据门户
- ps提示“脚本错误-50出现一般Photoshop错误的解决方法
- “读心术”再升级,数字识别准确率可达90%
- 象棋软件最强手机版_我说它是地表手机最强清理软件,没意见吧
- PHP获取git提交信意_代码提交规范检查与修复 php_codesniffer + composer-git-hooks
- 2022年电工杯B题参赛历程
- pyLDA系列︱考量时间因素的动态主题模型(Dynamic Topic Models)
- 使用JQuery.slideBox实现图片滚动效果
- 使用kali破解win7密码
- C语言编程入门——综合练习(一)
- 与门非门在电子计算机中的应用,与非门电路
- java给文件夹加密码_用JavaScrpt 实现文件夹轻松加密 (转)
- ips细胞治疗糖尿病研究进展综述
- 程序员专属段子集锦 10/10
- 网易云信圈组上线实时互动频道,「破冰」弱关系社交
- python sys.path用法
- 「String用法总结」
- 用python画微信表情_【一点资讯】“裂开了,苦涩了,翻白眼”!我用Python画出微信新出的表情包 www.yidianzixun.com...
热门文章
- 机械秒表的使用方法_秒表的使用方法!
- “苹果”在中国的血汗工厂
- Task 编程中的异常处理
- [kaggle]泰坦尼克预测(代码解析)
- 纯CSS3模拟iPhone X背景切换动画
- 匹兹堡大学约翰斯敦计算机学院,英语翻译翻译Every human being,no matter what he is doing,gives off...
- Engine中如何实现ArcMap中的Split Polygons
- 计算机休眠会断电吗,电脑「睡眠」和「休眠」原来有这么大区别,下次别用错了。...
- TensorFlow2.0-GPU加速
- 日记侠:如何用手机月入万元,只需从这5步开始