社区
ATL
帖子详情
分都用完拉!最后100,请问如何将unsigned char[]转成SAFEARRAY,以及如何将SAFEARRAY转回来?
pkzl888
2003-10-21 11:45:07
在idl中定义[in]SAFEARRAY(unsigned char) message,函数为STDMETHODIMP getdata(SAFEARRAY * message).要把message转成unsigned char 使用啊!拜托!!
...全文
65
2
打赏
收藏
分都用完拉!最后100,请问如何将unsigned char[]转成SAFEARRAY,以及如何将SAFEARRAY转回来?
在idl中定义[in]SAFEARRAY(unsigned char) message,函数为STDMETHODIMP getdata(SAFEARRAY * message).要把message转成unsigned char 使用啊!拜托!!
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
2 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
shudingbo
2003-10-21
打赏
举报
回复
http://expert.csdn.net/Expert/topic/2363/2363317.xml?temp=.3947565
________
看代码
flyingjust
2003-10-21
打赏
举报
回复
unsigned char pMemData=your memory!
unsigned char* pData =NULL; SAFEARRAY *psa = SafeArrayCreateVector( VT_UI1, 0, llen );
SafeArrayAccessData( psa, (void**)&pData );
memcpy( pData, pMemData, llen );
SafeArrayUnaccessData(psa);
delete pMemData;// clean up buffer
Access
unsigned char* pBuffer=NULL;
SafeArrayAccessData( message, (void**)&pBuffer );
lLength = pSA->rgsabound->cElements; //大小
pBuffer 就是数据访问指针
.....
SafeArrayUnaccessData( pSA );
标准MFC WinSock ActiveX控件开发实例(II)高级篇
主要利用VARIANT类型作参数进行的网络数据传送和接收,以及
SAF
EAR
RAY
,BSTR的详细使用方法。 另外还提供该控件在VC,VB下的调用方式以及相关数据的处理。 关键字:ActiveX,Socket,VARIANT,
SAF
EAR
RAY
,BSTR。 回顾:在上一篇文章《标准MFC WinSock ActiveX控件开发实例》中我们详细介绍了控件的开发过程,以及接口和事件的 添加和响应方法。现在我们将继续上次没有写完的控件继续进行开发,并完善作为一个WinSock控件应该具备的功能。 二、按照前一篇文章提到的知识,现在我们来添加两个新的接口分别是SendData()和GetData(),它们看起来如下: //网络数据发送,在指定的超时时间内进行发送然后返回,成功返回实际发送字节数,否则返回负数 long CMFCWinSockCtrl::SendData(const VARIANT FAR& Data, const VARIANT FAR& DataType, const VARIANT FAR& DataLength, const VARIANT FAR& TimeOut) { // TODO: Add your dispatch handler code here return 0; } //获取数据,并指定获取数据的超时时间,返回实际获取到的数据长度,否则返回负数 long CMFCWinSockCtrl::GetData(VARIANT FAR* Data, const VARIANT FAR& DataType, const VARIANT FAR& DataMaxLength, const VARIANT FAR& TimeOut) { // TODO: Add your dispatch handler code here return 0; } 两个接口的参数除了第一个参数外,其它都类似。SendData()是发送数据,不要求将数据带回,因此直接用 VARIANT,而GetData()则要求将数据带
回来
给调用者,因此定义为 VARIANT *类型,第二个参数DataType故名思义是定义所传送或接收数据的类型,第三个参数是传送或接收数据的长度,这里的长度以
char
作为一个长度,假如传入的类型是int类型,则长度为4,如果定义的是字符串,一个中文字符占用2个长度。
最后
一个参数,是网络发送或读取时的超时时间。 三、为Connect()接口添加源代码,看起来如下: //网络数据发送,在指定的超时时间内进行发送然后返回,成功返回实际发送字节数,否则返回负数 long CMFCWinSockCtrl::SendData(const VARIANT FAR& Data, const VARIANT FAR& DataType, const VARIANT FAR& DataLength, const VARIANT FAR& TimeOut) { // TODO: Add your dispatch handler code here if(!OnlySock) return -1;//网络尚未开始建立连接 int gDataType = VariantToLong(DataType); long gDataLength = VariantToLong(DataLength); int gTimeOut = VariantToLong(TimeOut); if(gDataType < 0) return -2; if(gDataLength <= 0) return -2; if(gTimeOut < 0) return -2; switch(gDataType) { case 0://默认形式,这时如果发现Data为整型数组,将不进行任何
转
换,直接把一个int传给一个
char
传送(数据可能溢出范围) case 1://当指定该值为1时,当Date为长整型数组时,将把一个long
转
换成四个
char
传送 case 2://当指定该值为2时,当Date为整型数组时,将把一个int
转
换成四个
char
传送 case 3://当指定该值为3时,当Date为无符号短整型数组时,将把一个
unsigned
short
转
换成两个
char
传送 case 4://当指定该值为4时,当Date为BYTE数组时,将把一个BYTE
转
换成一个
char
传送 case 5://当指定该值为5时,当Date为短整型数组时,将把一个short
转
换成两个
char
传送 case 6://当指定该值为6时,当Date为浮点型数组时,将把一个float
转
换成四个
char
传送 case 7://当指定该值为7时,当Date为双精度数组时,将把一个double
转
换成八个
char
传送 break; default://如果不在上面取值范围内,将按当前的Data相应类型进行传送 break; } timeval tv; fd_set fdwrite; int len = 0; long m = 0; long n = 0; long changetype = 0;//将浮点型数据进行类型
转
换,再进行传送 VARIANT gData; VariantInit(&gData); //送出信息至服务器 FD_ZERO(&fdwrite); tv.tv_sec = gTimeOut;//指定时间后返回 tv.tv_usec = 0; FD_SET(OnlySock,&fdwrite);//是否可以发送数据 select(0,NULL,&fdwrite,NULL,&tv);
char
*buffer = NULL; if(FD_ISSET(OnlySock,&fdwrite)) { switch(Data.vt) { case VT_BSTR://按字符串形式发送 buffer = _com_util::ConvertBSTRToString(Data.bstrVal); break; case VT_BYREF|VT_UI1: //按BYTE*形式发送 buffer = new
char
[gDataLength]; memcpy(buffer,Data.pbVal,gDataLength); break; case VT_BYREF|VT_I1://按
char
* 发送 buffer = new
char
[gDataLength]; memcpy(buffer,Data.pcVal,gDataLength); break; case VT_AR
RAY
|VT_I4://以长整型数组发送 gData.vt = VT_I4; if(gDataType!=0)//long =
char
*4 { //sizeof(long),在这里一个长整型的长度为4个
char
buffer = new
char
[gDataLength]; for(m=0,n=0; n>24)&0xff; buffer[m++] = (gData.lVal>>16)&0xff; buffer[m++] = (gData.lVal>>8)&0xff; buffer[m++] = gData.lVal&0xff; } } else//long =
char
*1 //数据可能溢出 { buffer = new
char
[gDataLength]; for(m=0,n=0; n
Saf
eAr
ray
GetElement(Data.par
ray
,&n,&gData.lVal); buffer[n] = (
char
)gData.lVal; } } break; case VT_AR
RAY
|VT_INT://以整型数组发送 gData.vt = VT_INT; if(gDataType != 0) { //一个int等于四个
char
buffer = new
char
[gDataLength]; for(m=0,n=0; n>24)&0xff; buffer[m++] = (gData.intVal>>16)&0xff; buffer[m++] = (gData.intVal>>8)&0xff; buffer[m++] = gData.intVal&0xff; } } else { buffer = new
char
[gDataLength]; for(n=0; n
Saf
eAr
ray
GetElement(Data.par
ray
,&n,&gData.intVal); buffer[n] = (
char
)gData.intVal; } } break; case VT_AR
RAY
|VT_UI1://以BYTE数组发送 gData.vt = VT_UI1;//一个
char
等于一个BYTE不必进行
转
换 buffer = new
char
[gDataLength]; for(n=0; n
Saf
eAr
ray
GetElement(Data.par
ray
,&n,&gData.bVal); buffer[n] = gData.bVal; } break; default://在这里没有一一列出其它类型,剩下的就由阁下进行数据
转
换处理了,我就偷懒了^_^ return -3;//传入的数据类型不被支持 } len = send(OnlySock, buffer, gDataLength, 0);//发送数据 delete[] buffer; buffer = NULL; if (len>24)&0xff; buffer[1] = (lData>>16)&0xff; buffer[2] = (lData>>8)&0xff; buffer[3] = lData&0xff; //4个
char
组成一个long lData_2 = ((buffer[0]&0xff)<<24) + ((buffer[1]&0xff)<<16) + ((buffer[2]&0xff)<<8) + (buffer[3]&0xff); 四、现在来看看GetData()的处理,具体实现,请看如下代码: // TODO: Add your dispatch handler code here if(!OnlySock) return -1;//网络尚未开始建立连接 int gDataType = VariantToLong(DataType); long gDataMaxLength = VariantToLong(DataMaxLength); int gTimeOut = VariantToLong(TimeOut); if(gDataType < 0) return -2; if(gDataMaxLength <= 0) return -2; if(gTimeOut < 0) return -2; switch(gDataType) { case 0://默认形式,这时如果发现Data为整型数组,将不进行任何
转
换,直接把一个int传给一个
char
传送(数据可能溢出范围) case 1://当指定该值为1时,当Date为长整型数组时,将把一个long
转
换成四个
char
传送 case 2://当指定该值为2时,当Date为整型数组时,将把一个int
转
换成四个
char
传送 case 3://当指定该值为3时,当Date为无符号短整型数组时,将把一个
unsigned
short
转
换成两个
char
传送 case 4://当指定该值为4时,当Date为BYTE数组时,将把一个BYTE
转
换成一个
char
传送 case 5://当指定该值为5时,当Date为短整型数组时,将把一个short
转
换成两个
char
传送 case 6://当指定该值为6时,当Date为浮点型数组时,将把一个float
转
换成四个
char
传送 case 7://当指定该值为7时,当Date为双精度数组时,将把一个double
转
换成八个
char
传送 break; default://如果不在上面取值范围内,将按当前的Data相应类型进行传送 break; } timeval tv; fd_set fdread; int len = -3;//如果找不到该连接,则返回-3 long n = 0; long m = 0; long changetype = 0; VARIANT gData; VariantInit(&gData);
char
*buffer=NULL; buffer = new
char
[gDataMaxLength+1]; memset(buffer, 0, gDataMaxLength+1); FD_ZERO(&fdread); tv.tv_sec = gTimeOut;//超过指定时间后返回 tv.tv_usec = 0; FD_SET(OnlySock,&fdread);//是否可以读取数据 select( 0,&fdread,NULL,NULL,&tv); if(FD_ISSET(OnlySock,&fdread)) { len = recv(OnlySock, buffer, gDataMaxLength, 0); if (len<=0) { delete[] buffer; return -102;//无法读取数据,对方可能已断开连接 } if(lenvt) { case VT_BSTR://按字符串形式接收 buffer[gDataMaxLength] = '\0'; Data->bstrVal = _com_util::ConvertStringToBSTR(buffer); break; case VT_BYREF|VT_UI1: //按BYTE*形式接收 memcpy(Data->pbVal,buffer,gDataMaxLength); break; case VT_BYREF|VT_I1://按
char
* 形式接收 memcpy(Data->pcVal,buffer,gDataMaxLength); break; case VT_BYREF|VT_I4://以长整型指针接收 buffer[gDataMaxLength]='\0'; for(n=0; nplVal[n] = buffer[n]; } break; case VT_AR
RAY
|VT_I4://以长整型数组接收 gData.vt = VT_I4; if(gDataType != 0) { for(m=0,n=0; n
ray,&n,&gData.lVal); m = m+4; } } else { for(n = 0; npar
ray
,&n,&gData.lVal); } } break; case VT_AR
RAY
|VT_INT://以整型数组接收 gData.vt = VT_INT; if(gDataType != 0) { for(m=0,n=0; n
ray,&n,&gData.intVal); m = m+4; } } else { for(n = 0; npar
ray
,&n,&gData.intVal); } } break; case VT_AR
RAY
|VT_UI1://以BYTE数组接收 gData.vt = VT_UI1; for(n = 0; npar
ray
,&n,&gData.bVal); } break; default://其它类型,请各位看官自行实现处理,嘿嘿 delete[] buffer; return -3;//无法识别传入的数据类型 } } else { delete[] buffer; return 0;//网络数据读取超时 } VariantCl
ear
(&gData); delete[] buffer; return len; 五、接下来,我们看看VC和VB如何调用该控件: VC调用控件方式: 新建一对话框工程,然后在工程中添加该控件,设置如下图: 图一 创建新对话框工程,并加入控件 响应控件的断网和数据到达事件,设置如下图: 图二 响应控件的两个事件 添加相应代码,看起来如下: void CTestMFCWinSockDlg::OnRecvSockEventMfcwinsockctrl1() { // TODO: Add your control notification handler code here
SAF
EAR
RAY
BOUND Bound[1];//一维数组 Bound[0].lLbound=0; Bound[0].cElements=
100
;//该一维数组最大接收
100
个元素 VARIANT *data; data = new VARIANT; VariantInit(data); data->vt = VT_AR
RAY
|VT_I4;//指明为长整型数组 data->par
ray
=
Saf
eAr
ray
Create(VT_I4,1,Bound);//创建
SAF
EAR
RAY
结构 long l = m_sock.GetData(data, COleVariant((long)0), COleVariant((long)
100
), COleVariant((long)3)); if(l<=0) { ;//在这里判断出错信息,并作相应处理,我就偷懒了. }
char
pData[
100
]={0};//这里以字符数组显示结果 long change = 0; for(long n=0; npar
ray
,&n,&change); pData[n] = (
char
)change; } CString mess; mess.Format("%s",pData); AfxMessageBox(mess);
Saf
eAr
ray
Destroy(data->par
ray
); delete data; } void CTestMFCWinSockDlg::OnCloseWinsockMfcwinsockctrl1() { // TODO: Add your control notification handler code here m_sock.DisConnect();//调用断开连接接口 AfxMessageBox("服务器断开了该次连接,请检查!"); } void CTestMFCWinSockDlg::OnConnect() { // TODO: Add your control notification handler code here UpdateData(TRUE); if(!m_sock.Connect(COleVariant(m_ip),COleVariant(m_port))) AfxMessageBox("与服务器建立连接失败,请确认服务器是否存在!"); } VB调用控件方式: VB时面调用要方便很多,这得益于VB的很多自动化功能,请看下图: 图三 VB调用控件方法 同样,双击我们的控件,然后添加控件事件,如下图: 图四 VB响应控件事件 然后,添加相关代码如下: Private Sub Command1_Click() MFCWinSock1.Connect CStr(ip), CLng(port) End Sub Private Sub Command2_Click() MFCWinSock1.SendData "SendData: 欢迎使用!", 0, 50, 3 End Sub Private Sub MFCWinSock1_CloseWinsock() MFCWinSock1.DisConnect MsgBox "服务器断开了连接,请检查!" End Sub Private Sub MFCWinSock1_RecvSockEvent() Dim data As Variant Dim data2(
100
) As Long Dim data3 As String Dim l As Long data = data2 '在VB里当把一个Variant变量data等于另一个确定变量data2时,data将被初始化为与data2相同的类型变量 'data = data3 '如果让data等于data3,那么data将变成字符串型的变量参数 l = MFCWinSock1.GetData(data, 0,
100
, 3) '这时data里面已存放了接收到的数据 data3 = data(0) '这里只显示接收到的首字符编码 MsgBox data3 End Sub 大家可以看到,对于
SAF
EAR
RAY
类型的数据进行相关处理也并不可怕,由于在源码里给出了具体代码和详细注解,在这里我就不再赘述了, 至于BSTR和
char
*类型的数据,相信不用我多说,大家也已经知道如何使用了。 结束语: 全文至此暂告一段落,本文向大家展示了MFC ActiveX控件的魅力,以及所用的VARIANT类型参数,还详细给出了WinSock的开发代码, 以用在VC,VB的调用方法,由于这段时间忙于一些新项目的开发,因此没办法花太多时间进行详细解释,所以很多地方都直接给出源代码 再加上注解,而没有进行通俗的讲解,还请各位读者仔细查看源代码。 本控件目前只能作为客户端,阁下还可以继续进行完善,比如进行端口的监听,实现服务器的相关处理等等,但这已经不是本文的目的, 授人以鱼,不如授人如渔,剩下的功能,就由各位读者去实现了,也欢迎与我进行交流,谢谢! 另外:本文的示例,需要一个服务器程序,大家可以在网上随便下载一下进行测试,我就不提供了。 声明: 部分资料来源于网络,本文所用的所有源代码仅供非商业用途,并请保留原版权,否则后果自负! 欢迎大家拍砖,指正错误或不足的地方,一起探导更好的方法。 欢迎访问www.59186618.com,感谢您的支持!
将图像BYTE(
unsigned
char
)数组
转
换为VARIANT类型
因为近期工作需要完成OCX控件同时支持C#与C++调用,所以接口设置就会遇上些问题。在需要将图片的内存数据(buffer)传入控件时,如果按照C++惯例,设计接口参数类型为
unsigned
char
*,就会存在被C#识别为ref byte的参数,这样就只能够传递一个像素的数据(8bit灰度图像)。
数据库
unsigned
char
*类型图片存进
loadimage1();测试: void Caccess_test_1Dlg::loadimage1()//存入
unsigned
char
*类型的数据图片 { CFileException e; Invalidate(); //输入图片测试 CString sFilePathName = L"D:\\bridge.bmp"; m_Pic....
Saf
eAr
ray
首先介绍
Saf
eAr
ray
使用,在介绍
Saf
eAr
ray
中的结构。看完该节文章,
Saf
eAr
ray
的陌生感一扫而去。
Saf
eAr
ray
在ADO编程中经常使用。它的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成
Saf
eAr
ray
。实质上
Saf
eAr
ray
就是将通常的数组增加一个描述符,说明其维数、长度、边界、元素类型等
关于
Saf
eAr
ray
的使用说明
猛料资料,首先介绍
Saf
eAr
ray
使用,在介绍
Saf
eAr
ray
中的结构。看完该节文章,
Saf
eAr
ray
的陌生感一扫而去。
Saf
eAr
ray
在ADO编程中经常使用。它的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成
Saf
eAr
ray
。实质上
Saf
eAr
ray
就是将通常的数组增加一个描述符,说明其维数、长度
ATL
3,245
社区成员
48,537
社区内容
发帖
与我相关
我的任务
ATL
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
复制链接
扫一扫
分享
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章