因为近期工作需要完成OCX控件同时支持C#与C++调用,所以接口设置就会遇上些问题。在需要将图片的内存数据(buffer)传入控件时,如果按照C++惯例,设计接口参数类型为unsigned char*,就会存在被C#识别为ref byte的参数,这样就只能够传递一个像素的数据(8bit灰度图像)。
这么一来,就需要使接口参数类型能够成功传递一个buffer数组,那么就想到了VARIANT类型,它可以将数组封装起来,包含数组的维度与长度以及类型信息。这样一来就可以满足要求了。
根据CImage类获得图像数据(BYTE数组):
///打开图片
CImage img;
img.Load(csName);
///获得图像数据
int pitch = img.GetPitch();
int bytes = abs(pitch) * img.GetHeight();
BYTE * src = (BYTE*)img.GetBits();
BYTE* tempBuffer = new BYTE[bytes];
int sizeLine = abs(pitch);
///这部分图像内存的处理将另开一篇博文详细解释,此处实现比较粗糙
for ( int line = 0; line < img.GetHeight(); ++line ){
memcpy(tempBuffer + line*sizeLine, src + line*pitch, sizeLine);
}
///将图像数据封装为接口需要的VARIANT类型
VARIANT pImgBuffer;
VariantInit(&pImgBuffer);
SAFEARRAY *psa = NULL;
SAFEARRAYBOUND rgsabound;
rgsabound.cElements = bytes;
rgsabound.lLbound = 0;
psa = SafeArrayCreate(VT_UI1, 1, &rgsabound);
if ( psa == NULL )
return;
BYTE *pBitmapData = NULL;//new BYTE[bytes];(不需要new)
SafeArrayAccessData(psa, (void **)&pBitmapData);
memcpy(pBitmapData, tempBuffer, bytes);
///将SAFEARRAY放入VARIANT中,并设置类型
pImgBuffer.vt = VT_ARRAY | VT_UI1;
SafeArrayCopy(psa, &pImgBuffer.parray);
SafeArrayUnaccessData(psa);
//这里也就不需要使用delete释放pBitmapData所指向的空间
//YOUR_INTERFACE(pImgBuffer/*VARIANT*/, img.GetHeight(), img.GetWidth());
if ( tempBuffer )
delete[] tempBuffer;
tempBuffer = NULL;
SafeArrayDestroy(psa);
img.Destroy();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
接口内实现:
//VARIANT* pPixArray;(接口参数)
unsigned char* pBuffer = NULL;
SafeArrayAccessData(pPixArray.parray, (void**)&pBuffer);
///此处使用pBuffer所指向的数据
SafeArrayUnaccessData(pPixArray.parray);
HRESULT ret = VariantClear(&pPixArray);
|