|
Posted on 2006-10-05 18:26 奔跑的阿甘 阅读(2061) 评论(0) 编辑 收藏 引用 所属分类: COM/ATL
COM数据类型 Michael 2006年10月5日 本文根据DON BOX大师《Essential COM》第2.11章节文章,对COM中IDL的数据类型的用法进行了总结。
IDL数据类型的设计思想是要保证类型的“语言独立”和“平台独立”,例如它需要能被C++/VB/Java等语言和Windows(各版本)和Solaris等平台识别和支持。
1。基本类型 全是小写的字符表示。 包括:boolean, byte, small, short, long, hyper, float, double, char, wchar_t, enum, 接口指针。这些类型我们并不陌生。
2。OLECHAR类型 这是COM中的字符类型。例如:HRESULT Method([in,string] const OLECHAR* pwsz);"string"属性表示pwsz是个OLECHAR数组。 在WIN32/Solaris平台上OLECHAR只是简单地被定义为wchar_t类型。 我们可以通过COM提供的宏OLESTR把一个普通的字符串转换为OLECHAR*类型:const OLECHAR *pwsz = OLESTR("Hello")。
WIN32提供的TCHAR类型随着预编译宏的定义而不同,为防止代码的冗余繁琐,Don Box大师编写了相关类和函数,用于把TCHAR*类型转换为OLECHAR*类型。 ustring.h提供了_U,_UNCC类用于把TCHAR*类型转换为OLECHAR*类型,并提供了ustrncpy等串操作的重载版本(接受char,wchar_t为参数类型)。
  1 /**//////////////////////////////////////////////////////////////////////////////// 2 // 3 // ustring.h - Copyright 1997, Don Box 4 // 5 // This file contains overloaded ustrcpy, ustrcat, and ustrlen that 6 // take either wchar_t or char strings for either argument and map to 7 // the appropriate CRT routine to do the work. The routines are inlined 8 // and incur no additional overhead. 9 // 10 // size_t ustrlen(const uchar *p); 11 // uchar *ustrcpy(uchar *p1, const uchar *p2); 12 // uchar *ustrcat(uchar *p1, const uchar *p2); 13 // 14 // where uchar = { wchar_t , char } 15 // 16 // This file contains the prototypes for several conversion routines 17 // that are used by the String816 class for duplicating/converting strings 18 // on the fly. 19 // 20 // uxdup(const char *psz) - returns a new-ed wchar_t string based on psz 21 // uxdup(const wchar_t *psz) - returns a new-ed char string based on psz 22 // 23 // Finally, this file contains two class definitions: 24 // 25 // _U - converts const uchar * to const uchar * 26 // _UNCC - converts const uchar * to uchar * (needed for non-const correct code) 27 // 28 // Usage: 29 /**//* 30 31 void f(const OLECHAR *pwsz, HWND hwnd) 32 { 33 TCHAR sz[MAX_PATH]; 34 GUID guid; 35 ustrcpy(sz, pwsz); // overloads to correct copy/conversion routine 36 SetWindowText(hwnd, _U(pwsz)); // _U temporarily dups buffer if needed 37 GetWindowText(hwnd, sz, MAX_PATH); 38 CLSIDFromString(_UNCC(sz), &guid); // _UNCC needed because api non-const-correct 39 } 40 41 */ 42 43 #ifndef _USTR_H 44 #define _USTR_H 45 46 #include <limits.h> 47 48 inline size_t ustrlen(const wchar_t *psz) 49  { 50 return wcslen(psz); 51 } 52 53 inline size_t ustrlen(const char *psz) 54  { 55 return strlen(psz); 56 } 57 58 inline char *ustrcpy(char *pszTarget, const wchar_t *pszSrc) 59  { 60 return wcstombs(pszTarget, pszSrc, INT_MAX), pszTarget; 61 } 62 63 inline wchar_t *ustrcpy(wchar_t *pszTarget, const wchar_t *pszSrc) 64  { 65 return wcscpy(pszTarget, pszSrc), pszTarget; 66 } 67 68 inline char *ustrcpy(char *pszTarget, const char *pszSrc) 69  { 70 return strcpy(pszTarget, pszSrc), pszTarget; 71 } 72 73 inline wchar_t *ustrcpy(wchar_t *pszTarget, const char *pszSrc) 74  { 75 return mbstowcs(pszTarget, pszSrc, INT_MAX), pszTarget; 76 } 77 78 inline char *ustrcat(char *pszTarget, const wchar_t *pszSrc) 79  { 80 return wcstombs(pszTarget + ustrlen(pszTarget), pszSrc, INT_MAX), pszTarget; 81 } 82 83 inline wchar_t *ustrcat(wchar_t *pszTarget, const wchar_t *pszSrc) 84  { 85 return wcscat(pszTarget, pszSrc); 86 } 87 88 inline char *ustrcat(char *pszTarget, const char *pszSrc) 89  { 90 return strcat(pszTarget, pszSrc); 91 } 92 93 inline wchar_t *ustrcat(wchar_t *pszTarget, const char *pszSrc) 94  { 95 return mbstowcs(pszTarget + ustrlen(pszTarget), pszSrc, INT_MAX), pszTarget; 96 } 97 98 // these two routines are equivalent to strdup but convert 99 // instead of just copying 100 101 wchar_t *uxdup(const char *psz); 102 char *uxdup(const wchar_t *pwsz); 103 104 105 // String816 maps const wchar_t * and const char * to 106 // either const wchar_t * or const char * depending on context 107 class String816 108  { 109 wchar_t *m_pwsz; 110 char *m_psz; 111 BOOL m_bIsWide; 112 public: 113 String816(const char *psz) 114 : m_pwsz(0), m_psz((char*)psz), m_bIsWide(FALSE) 115 { 116 } 117 118 String816(const wchar_t *pwsz) 119 : m_pwsz((wchar_t*)pwsz), m_psz(0), m_bIsWide(TRUE) 120 { 121 } 122 123 operator const wchar_t * (void) 124 { 125 if (!m_bIsWide && m_pwsz == 0) 126 m_pwsz = uxdup(m_psz); 127 return m_pwsz; 128 } 129 130 operator const char * (void) 131 { 132 if (m_bIsWide && m_psz == 0) 133 m_psz = uxdup(m_pwsz); 134 return m_psz; 135 } 136 137 ~String816(void) 138 { 139 if (m_bIsWide && m_psz) 140 free(m_psz); 141 else if (!m_bIsWide && m_pwsz) 142 free(m_pwsz); 143 } 144 }; 145 146 typedef String816 _U; 147 // class _UNCC adds non-const conversion operators to String816 148 class _UNCC : public String816 149  { 150 public: 151 _UNCC(const char *psz) 152 : String816(psz) 153 { 154 } 155 156 _UNCC(const wchar_t *pwsz) 157 : String816(pwsz) 158 { 159 } 160 161 operator wchar_t * (void) 162 { 163 return (wchar_t*)operator const wchar_t *(); 164 } 165 166 operator char * (void) 167 { 168 return (char*)operator const char *(); 169 } 170 171 }; 172 173 174 #endif 175 176 ---------------------------------------------- 177 /**//////////////////////////////////////////////////////////////////////////////// 178 // 179 // ustring.cpp - Copyright 1997, Don Box 180 // 181 // This file contains the implementation of several conversion routines 182 // that are used by the String816 class for duplicating/converting strings 183 // on the fly. 184 // 185 // uxdup(const char *psz) - returns a new-ed wchar_t string based on psz 186 // uxdup(const wchar_t *psz) - returns a new-ed char string based on psz 187 // 188 189 #ifndef _USTRING_CPP 190 #define _USTRING_CPP 191 192 wchar_t *uxdup(const char *psz) 193  { 194 size_t cch = strlen(psz) + 1; 195 wchar_t *pwszResult = (wchar_t*)malloc(cch * sizeof(wchar_t)); 196 if (pwszResult) 197 mbstowcs(pwszResult, psz, cch); 198 return pwszResult; 199 } 200 201 char *uxdup(const wchar_t *pwsz) 202  { 203 size_t cch = wcslen(pwsz) + 1; 204 char *pszResult = (char*)malloc(sizeof(char) * cch); 205 if (pszResult) 206 wcstombs(pszResult, pwsz, cch); 207 return pszResult; 208 } 209 210 #endif
3。BSTR BSTR是一个LENGTH-PREFIXED,NULL-TERMINATED的OLECHAR字符串。 在JAVA,VB中使用的COM接口文本参数都是BSTR类型。
BSTR的内存管理问题:COM提供了若干API用于分配释放BSTR内存,包括:
 BSTR内存管理函数 1 // 分配和初始化BSTR 2 BSTR SysAllocString(const OLECHAR *psz); 3 BSTR SysAllocStringLen(const OLECHAR *psz, UINT cch); 4 5 // 重分配和初始化BSTR 6 INT SysReAllocString(BSTR *pbstr, const OLECHAR *psz); 7 INT SysReAllocStringLen(BSTR *pbstr, const OLECHAR *psz, UINT cch); 8 9 // 释放BSTR 10 void SysFreeString(BSTR bstr); 11 12 // 长度前缀转换为字符或字节 13 UINT SysStringLen(BSTR bstr); 14 UINT SysStringByteLen(BSTR bstr); BSTR的内存由谁分配:若BSTR作为接口方法的传入参数,则调用方负责分配和释放;若作为传出参数,则接口对象负责分配,调用方负责释放。 当BSTR作为传入参数时,可采用以下类似前面_U,_UNCC的_UBSTR类来简化代码:
 _UBSTR 1 class _UBSTR { 2 BSTR m_bstr; 3 public: 4 _UBSTR(const char *psz) 5 : m_bstr(SysAllocStringLen(0, strlen(psz))) { 6 mbstowcs(m_bstr, psz, INT_MAX); 7 } 8 9 _UBSTR(const wchar_t *pwsz) 10 : m_bstr(SysAllocString(pwsz)) {} 11 12 operator BSTR (void) const { return m_bstr;} 13 ~_UBSTR(void) {SysFreeString(m_bstr);} 14 };
4。VARIANT, VARIANTARG VARIANT是个UNION类型,它容纳前面提到的基本类型中的一个子集类型,具体支持哪个类型由对应的鉴别器指定,如VT_I2对应short类型。 VARIANTARG作为方法参数,VARIANT作为方法结果,但是两个是同一个联合,仅仅名称不同而已。
 VARIANT管理函数 1 //请参考MSDN获得详细含义 2 3 void VariantInit(VARIANTARG *pvarg); 4 5 HRESULT VariantClear(VARIANTARG *pvarg); 6 7 HRESULT VariantCopy(VARIANTARG *plhs, VARIANTARG *prhs); 8 9 HRESULT VariantCopyInd(VARIANT *plhs, VARIANTARG *prhs); 10 11 HRESULT VariantChangeType(VARIANTARG *plhs, VARIANTARG *prhs, USHORT wFlags, VARTYPE vtlhs); 12 13 HRESULT VariantChangeTypeEx(VARIANTARG * plhs, VARIANTARG *prhs, LCID lcid, USHORT wFlags, VARTYPE vtlhs); 14  EXAMPLE 1 1 //向接口方法传递一整型 2 3 VARIANT var; 4 VariantInit(&var); 5 V_VT(&var) = VT_I4; //设置DISCRIMINATOR(鉴别器) 6 V_I4(&var) = 100; //传递整型值100 7 8 pObject->CallIt(var);//调用方法 9 VariantClear(&var); //释放资源  EXAMPLE 2 1 // CallIt方法内部采用字符串的VARIANT 2 // 所以调用了VARIANT API进行了类型转换 3 4 STDMETHODIMP MyObject::CallIt(/**//*[in]*/VARIANT var) { 5 VARIANT var2; 6 VariantInit(&var2); 7 HRESULT hr = VariantChangeType(&var2, &var, 0, VT_BSTR); 8 if (SUCCEEDED(hr)) { 9 ustrcpy(m_sz, SAFEBSTR(V_BSTR(&var2))); 10 VariantClear(&var2); 11 } 12 return hr; 13 } 14 15 inline OLECHAR *SAFEBSTR(BSTR bstr) { 16 return b?b:OLESTR(""); 17 }5。COM接口 COM接口也可以作为方法参数进行传递,如: HRESULT GetObject([out] IDog **ppDog); HRESULT GetObject([in] REFIID riid, [out, iid_is(riid)] IUnknown **ppv); HRESULT GetObject([in] REFIID riid, [out, iid_is(riid)] void **ppv); (优先选择)
【完】
|