因爲項目開發須要,原有的程序用C++開發,可是現有用C#開發,因此須要對用C++開發的接口利用COM進行封裝,供c#語言調用,在此處用到一個字節數組,因此此處對其進行封裝。c#
SAFEARRAY* SafeArrayCreate( VARTYPE vt, unsigned int cDims, SAFEARRRAYBOUND * rgsabound );
VARTYPE 數組數據的類型,此處爲:VT_UI1表示1個字節的BYTE類型。具體類型以下:
VT_UI1 無符號1字節整數(BYTE)數組 VT_UI2 無符號2字節整數(WORD)數組 VT_UI4 無符號4字節整數(DWORD)數組 VT_UINT 無符號整數(UINT)數組 VT_INT 有符號整數(INT)數組 VT_I1 有符號1字節整數數組 VT_I2 有符號2字節整數數組 VT_I4 有符號4字節整數數組 VT_R4 IEEE 4字節浮點數(float)數組 VT_R8 IEEE 8字節浮點數(double)數組 VT_CY 8字節定點數貨幣值數組 VT_BSTR VB字符串數組 VT_DECIMAL 12字節定點數(大數字)數組 VT_ERROR 標準錯誤編號數組 VT_BOOL 布爾值數組 VT_DATE 日期型數組 VT_VARIANT VB Variant類型數組
cDims 表示數組維數,此處賦值爲1,表示一維數組數組
SAFEARRAYBOUND* rgsabound:Pointer to a vector of bounds (one for each dimension) to allocate for the array.函數
存放的是一組數據,每一組表明一維中數據的個數以及下標下界。測試
typedef struct tagSAFEARRAYBOUND { unsigned long cElements; //該維元素個數 unsigned long lLbound; //該未下標的下界 } SAFEARRAYBOUND;
HRESULT SafeArrayAccessData( SAFEARRAY * psa, void HUGEP ** ppvData );
SAFEARRAY* psa [in] SAFEARRAY指針ui
ppvData [out],數組指針,若獲取成功,能夠用下標方式訪問數組中的數據, (*ppvData)[i];spa
HRESULT SafeArrayUnaccessData( SAFEARRAY FAR* psa );
操做結果線程
S_OK 操做成功 | |
E_INVALIDARG 不合法的數針 | |
[ object, uuid(2D33B425-58DE-4D4C-BAC2-B39502E0644F), dual, nonextensible, helpstring("IComByteArray 接口"), pointer_default(unique) ] interface IComByteArray : IDispatch{ [id(1), helpstring("方法CreateArray")] HRESULT CreateArray([in] UINT nArraySize, [out,retval] VARIANT_BOOL* retVal); [id(2), helpstring("方法PutItem")] HRESULT PutItem([in]UINT itemIndex ,[in] BYTE content, [out,retval] VARIANT_BOOL* retVal); [id(3), helpstring("方法GetItem")] HRESULT GetItem([in]UINT itemIndex, [out,retval] BYTE* retVal); };
IDL文件中定義了以下接口:數組的建立、數據的put和get操做
/*********************************************************************** 文件名: ComByteArray.h 類名: CComByteArray 做者: 定義時間:2012-4-27 功能:字節數組COM封裝 ************************************************************************/ #pragma once #include "resource.h" // 主符號 #include "COMM_COM_Client.h" #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) #error "Windows CE 平臺(如不提供徹底 DCOM 支持的 Windows Mobile 平臺)上沒法正確支持單線程 COM 對象。定義 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可強制 ATL 支持建立單線程 COM 對象實現並容許使用其單線程 COM 對象實現。rgs 文件中的線程模型已被設置爲「Free」,緣由是該模型是非 DCOM Windows CE 平臺支持的惟一線程模型。" #endif class ATL_NO_VTABLE CComByteArray : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CComByteArray, &CLSID_ComByteArray>, public IDispatchImpl<IComByteArray, &IID_IComByteArray, &LIBID_COMM_COM_ClientLib, { public: CComByteArray(); ~CComByteArray(); DECLARE_REGISTRY_RESOURCEID(IDR_COMBYTEARRAY) BEGIN_COM_MAP(CComByteArray) COM_INTERFACE_ENTRY(IComByteArray) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } public: private: UINT m_nSize; //數組大小 SAFEARRAY* m_pSafeArray; //SAFEARRAY指針 VARIANT_BOOL m_bAutoDelete;//是否自動刪除 BYTE HUGEP* m_pContent; //數組數據內存首指針 STDMETHOD(CreateArray)(UINT nArraySize, VARIANT_BOOL* retVal); STDMETHOD(PutItem)(UINT itemIndex, BYTE content, VARIANT_BOOL* retVal); STDMETHOD(GetItem)(UINT itemIndex, BYTE* retVal); }; OBJECT_ENTRY_AUTO(__uuidof(ComByteArray), CComByteArray)
/************************************************************************ 函數名:Create 功能:建立指定大小的數組內容 參數:[in]nArraySize 數組大小 [out]retVal 操做結果 /************************************************************************/ STDMETHODIMP CComByteArray::CreateArray(UINT nArraySize, VARIANT_BOOL* retVal) { // TODO: 在此添加實現代碼 HRESULT hr; if (nArraySize < 0) { *retVal = VARIANT_FALSE; return E_INVALIDARG; } if (0 == nArraySize) { *retVal = VARIANT_TRUE; return S_OK; } SAFEARRAYBOUND rgsabound[1]; //定義數組維度信息並建立數組 rgsabound[0].lLbound = 0; rgsabound[0].cElements = nArraySize; m_nSize = nArraySize; m_pSafeArray = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == m_pSafeArray) { hr = ResultFromScode(E_OUTOFMEMORY); return hr; } hr = ::SafeArrayAccessData(m_pSafeArray, (void**)&m_pContent); //獲取數據數據內存首指針 if (FAILED(hr)) return hr; return S_OK; }
數據的插入:
/************************************************************************ 函數名:PutItem 功能:向指定下標的數組中存放內容 參數:[in]itemIndex 數組下標 [in]content 內容 [out]retVal 操做結果 /************************************************************************/ STDMETHODIMP CComByteArray::PutItem(UINT itemIndex, BYTE content, VARIANT_BOOL* retVal) { // TODO: 在此添加實現代碼 if (m_nSize <= itemIndex || itemIndex < 0) { *retVal = VARIANT_FALSE; return E_INVALIDARG; } m_pContent[itemIndex] = content; *retVal = VARIANT_TRUE; return S_OK; }
/************************************************************************ 函數名:GetItem 功能:獲取指定下標的數組內容 參數:[in]itemIndex 數組下標 [out]retVal 輸出數據位置指針 /************************************************************************/ STDMETHODIMP CComByteArray::GetItem(UINT itemIndex, BYTE* retVal) { // TODO: 在此添加實現代碼 if (m_nSize <= itemIndex || itemIndex < 0) { *retVal = VARIANT_FALSE; return E_INVALIDARG; } *retVal = m_pContent[itemIndex]; return S_OK; }
using System; using System.Collections.Generic; using System.Text; using COMM_COM_ClientLib; namespace COMMClientTest { class Program { static void Main(string[] args) { IComByteArray comByteArray = new ComByteArray(); //COM對象建立 comByteArray.CreateArray((uint)100); for (uint i = 0; i < 5; i++) //放入數據 { bool bRet = comByteArray.PutItem(i, (Byte)i); if (bRet) Console.WriteLine("Put Item Succ"); else Console.Write("Put Item Fail"); } Console.WriteLine("-----------------------------------"); for (uint i = 0; i < 5; i++) //讀取放入的數據 { Byte value; value = comByteArray.GetItem(i); Console.WriteLine(value); } Console.ReadLine(); } } }
測試結果:
//COM byteArray測試 void comTest() { CoInitialize(NULL); { IComByteArrayPtr ptr = NULL; //COM對象建立 ptr.CreateInstance(__uuidof(ComByteArray)); if (!ptr) { cout<<"Com Object Init Failed"<<endl; return ; } ptr->CreateArray(UINT(100)); //建立並放入數據 for (UINT i = 0; i < 5; i++) { ptr->PutItem(i, (BYTE)i); } for (UINT i = 0; i < 5; i++) //讀取數據 { BYTE value; value = ptr->GetItem(i); cout<<(int)value<<endl; } } CoUninitialize(); }
測試結果: