• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            <2006年6月>
            28293031123
            45678910
            11121314151617
            18192021222324
            2526272829301
            2345678

            統計

            • 隨筆 - 24
            • 文章 - 0
            • 評論 - 17
            • 引用 - 0

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            相冊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            BSTR CComBSTR及ATL字符串轉換宏
            一 BSTR及CComBSTR

            MSDN文檔中說,BSTR是四字節長度前綴的,NULL結尾的寬字符串,稱之為VB字符串或BINARY字符串。
            依次查找幾個頭文件,不難發現,BSTR被typedef成OLECHAR *,而OLECHAR被typedef成WCHAR(未定義OLE2ANSI預處理宏)或char (定義OLE2ANSI預處理宏);繼續順藤摸瓜,WCHAR被typedef成wchar_t,而wchar_t被typedef成unsigned short。

            最終的結果就是,BSTR被typedef成unsigned short *(未定義OLE2ANSI預處理宏)或char *(定義OLE2ANSI預處理宏)。

            原來BSTR只是一個指針。

            本文不考慮定義預處理宏OLE2ANSI的情況。

            在COM編程中,凡是使用BSTR的地方,我們可以使用類CComBSTR來代替BSTR。CComBSTR封裝了BSTR,通過各種重載構造函數和操作符重載,僅僅使用對象定義,type cast等簡單語句,就可以實現BSTR與各種類型字符串,包括LPSTR,LPOLESTR之間的轉換,賦值,連接,比較等操作。

            二 ATL字符串轉換宏
            除了CComBSTR類支持各種字符串類型到BSTR的轉換以外,ATL還有一組字符串轉換宏,可以方便的進行各種類型字符串之間的轉換。這些宏有統一的形式:X2[C]Y或Z2BSTR。其中X,Y,Z可以為A,W,T,OLE中的任一種,X與Y不相同;C表示轉換的目標類型為const——因此,這樣的組合方式總共有4x3x2+4=28種。

            根據預處理宏_UNICODE定義與否,T被替代成W或A,所以這28個轉換宏最終可以歸結為兩類:一類是A和W之間的轉換,另一類是A,W到BSTR的轉換。

            下面看看第一類中A2W的實現。
            // Exerpt from ATLCONV.H   
            #define A2W(lpa) (\
                    ((_lpa 
            = lpa) == NULL) ? NULL : (\
                        _convert 
            = (lstrlenA(_lpa)+1),\
                        ATLA2WHELPER((LPWSTR) alloca(_convert
            *2), _lpa, _convert)))

            A2W是支持從ANSI字符串到UNICODE字符串的轉換宏。可以看到,A2W的主體是一個?:表達式,根據源字符串是否為NULL,對冒號之前或之后的表達式進行求值。冒號后的部分又是一個逗號表達式:先計算源字符串的長度,再調用被定義為同名宏(大小寫不同)的轉換函數,轉換函數中調用MultiByteToWideChar系統函數進行具體的轉換,逗號表達式的值是轉換函數的返回值。最終,轉換宏的值是NULL或者轉換函數的返回值。

            值得注意的是,在A2W宏定義中引用了類似_lpa, _convert等標識符,那么這些標識符是什么,又是哪里來的呢?
            這就是為什么在使用這些字符串轉換宏之前,需要統一加上一句
            USES_CONVERSION;
            USES_CONVERSION也是宏定義,就是用來聲明轉換宏中使用的標識符的。

            另外,MSDN中特別提到,A和W之間的轉換(A2W,W2A),以及通過預處理宏_UNICODE翻譯成A和W之間轉換的宏,它們無一例外的都是從調用函數棧上分配空間存放轉換結果字符串。因此,轉換結果字符串在調用函數返回后自動被清除,也就是不能保留轉換結果用于調用函數外使用。

            與之相對,再看看第二類,A,W,T,OLE到BSTR的轉換宏實現。
            // Exerpt from ATLCONV.H
            inline BSTR OLE2BSTR(LPCOLESTR lp) {return ::SysAllocString(lp);}
            #if defined(_UNICODE)
            // in these cases the default (TCHAR) is the same as OLECHAR
                inline BSTR T2BSTR(LPCTSTR lp) {return ::SysAllocString(lp);}
                inline BSTR A2BSTR(LPCSTR lp) {USES_CONVERSION; 
            return A2WBSTR(lp);}
                inline BSTR W2BSTR(LPCWSTR lp) {
            return ::SysAllocString(lp);}
            #elif defined(OLE2ANSI)
            // in these cases the default (TCHAR) is the same as OLECHAR
                inline BSTR T2BSTR(LPCTSTR lp) {return ::SysAllocString(lp);}
                inline BSTR A2BSTR(LPCSTR lp) {
            return ::SysAllocString(lp);}
                inline BSTR W2BSTR(LPCWSTR lp) {USES_CONVERSION; 
            return ::SysAllocString(W2COLE(lp));}
            #else
                inline BSTR T2BSTR(LPCTSTR lp) {USES_CONVERSION; 
            return A2WBSTR(lp);}
                inline BSTR A2BSTR(LPCSTR lp) {USES_CONVERSION; 
            return A2WBSTR(lp);}
                inline BSTR W2BSTR(LPCWSTR lp) {
            return ::SysAllocString(lp);}
            #endif

            同樣,除了OLE2BSTR以外,A,W,T到BSTR的轉換根據是否定義預處理宏_UNICODE進行不同的處理,最終歸結為兩種類型的轉換:A2BSTR和W2BSTR。對于A2BSTR,由于BSTR也就是W,所以A2BSTR的轉換在理論上同A2W應該相同。

            但實際上,A2BSTR調用函數A2WBSTR,A2WBSTR內部從堆上分配空間,再調用系統轉換函數MultiByteToWideChar進行轉換——這就是A,W之間的轉換與2BSTR類型的轉換的根本不同之處;W2BSTR就簡單了,由于BSTR即是W字符串,因此不需要實際轉換,只需分配空間并拷貝源串作為轉換結果即可。

            對于OLE2BSTR,由于BSTR是從OLECHAR定義來的(見上面BSTR類型定義),因此不管預處理宏如何定義(包括OLE2ANSI是否定義),二者的類型始終是一致的,因此,從OLE到BSTR,并不需要進行實際的轉換,只需分配空間并拷貝源串作為轉換結果即可。

            總結下來,28個字符串轉換宏中,根據結果字符串存放位置分為兩類,一類是A,W之間的轉換宏,這一類宏的轉換結果字符串放在調用函數的棧空間,調用函數返回會該空間自動清除,第二類為目的類型為BSTR的轉換宏,其轉換結果字符串放在系統堆,在調用函數返回后結果字符串仍然存在。這是兩類轉換宏之間的最顯著差別。

            測試代碼
            // TestATLX2Y.cpp

            #include 
            <iostream>
            #include 
            <atlbase.h>
            using namespace std;

            #ifdef _UNICODE
            #define TCOUT wcout
            #else
            #define TCOUT cout
            #endif

            int main()
            {
            #ifdef _UNICODE
                TCOUT 
            << _T("----- Test with _UNICODE --------"<< endl;
            #else
                TCOUT 
            << _T("----- Test without _UNICODE --------"<< endl;
            #endif

                LPTSTR lptstr
            =_T("TCHAR is either char or wchar_t");
                LPSTR lpstr
            ="How can I indicate i'm a LPSTR?";
                LPWSTR lpwstr
            =L"I am a wide-character string";
                TCOUT 
            << _T("lptstr:"<< lptstr << endl;
                cout 
            << "lpstr:" << lpstr << endl;
                wcout 
            << L"lpwstr:" << lpwstr << endl;
                
                USES_CONVERSION;
                TCOUT 
            << _T("A2T:"<< A2T(lpstr) << endl;
                wcout 
            << L"A2W:" << A2W(lpstr) << endl;
                cout 
            << "T2A:" << T2A(lptstr) << endl;
                wcout 
            << L"T2W:" << T2W(lptstr) << endl;
                cout 
            << "W2A:" << W2A(lpwstr) << endl;
                TCOUT 
            << _T("W2T:"<< W2T(lpwstr) << endl;
                BSTR bstr;
                wcout 
            << L"A2BSTR:" << (bstr=A2BSTR(lpstr)) << endl;
                ::SysFreeString(bstr);
                wcout 
            << L"W2BSTR:" << (bstr=W2BSTR(lpwstr)) << endl;
                
                wcout 
            << L"T2BSTR:" << (bstr=T2BSTR(lptstr)) << endl;
                
            // How to know if we need to free the space pointered by returned value of T2BSTR?
                if((void *)bstr!=(void *)lptstr) ::SysFreeString(bstr);
                
                wcout 
            << L"OLE2BSTR:" << OLE2BSTR(lpwstr) << endl;
                
            return 0;
            }


            代碼運行結果:

            posted on 2011-12-03 22:56 小蔥蘸醬 閱讀(5286) 評論(0)  編輯 收藏 引用 所屬分類: COM

            97精品伊人久久大香线蕉| 精品国产91久久久久久久| 亚洲精品综合久久| 亚洲婷婷国产精品电影人久久| 久久中文字幕无码专区| 久久久久久久波多野结衣高潮| 久久精品国产第一区二区三区| 国内精品久久久久国产盗摄| 亚洲а∨天堂久久精品| 久久久久亚洲av无码专区| 久久精品亚洲福利| jizzjizz国产精品久久| 伊人久久大香线蕉成人| 国产精品99久久久久久宅男| 久久综合偷偷噜噜噜色| 精品久久久久久国产免费了| 一本久久知道综合久久| 久久精品亚洲男人的天堂| 精品久久久久久亚洲| 婷婷久久久亚洲欧洲日产国码AV| 久久免费99精品国产自在现线| 久久99国产精品久久久| 亚洲AV无码成人网站久久精品大| 亚洲人AV永久一区二区三区久久| 亚洲午夜久久久精品影院| 久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口 | 蜜臀av性久久久久蜜臀aⅴ| 久久久久国产一区二区三区| 久久九九亚洲精品| A狠狠久久蜜臀婷色中文网| 奇米综合四色77777久久| 少妇熟女久久综合网色欲| 亚洲午夜福利精品久久| 久久99国产精品99久久| 久久精品免费全国观看国产| 中文字幕久久波多野结衣av| 色婷婷噜噜久久国产精品12p| 久久黄视频| 久久亚洲国产成人影院| 亚洲AⅤ优女AV综合久久久| 欧美久久久久久午夜精品|