青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

  • 隨筆 - 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 小蔥蘸醬 閱讀(5326) 評論(0)  編輯 收藏 引用 所屬分類: COM


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美一区二区三区免费观看| 亚洲影视在线| 亚洲日产国产精品| 91久久精品一区| 99国产精品99久久久久久粉嫩| 一级日韩一区在线观看| 香蕉国产精品偷在线观看不卡| 久久综合婷婷| 99精品国产在热久久婷婷| 日韩视频中文字幕| 欧美在线综合| 国产精品第一区| 在线不卡a资源高清| 亚洲色在线视频| 欧美成人有码| 亚洲一区日韩在线| 欧美国产第一页| 国产亚洲欧洲| 亚洲视频播放| 亚洲自拍偷拍色片视频| 欧美日韩成人网| 激情亚洲网站| 久久国产精品久久久| 久久亚洲精品一区二区| 亚洲私人影院在线观看| 欧美精品在线视频| 亚洲精品1234| 欧美怡红院视频| 久久久久国产精品www| 国产麻豆日韩欧美久久| 一本色道久久综合| 午夜精品在线看| 国产精品草莓在线免费观看| 亚洲人成在线观看一区二区| 亚洲视频免费| 国产精品美女一区二区在线观看| 亚洲免费综合| 亚洲欧美久久久久一区二区三区| 亚洲第一伊人| 欧美激情国产精品| 欧美成人精品不卡视频在线观看 | 在线亚洲电影| 亚洲精品久久久久久下一站 | 亚洲福利视频三区| 香蕉久久a毛片| 男人的天堂亚洲在线| 亚洲精品偷拍| 久久久久国产精品一区三寸| 午夜亚洲激情| 久久www成人_看片免费不卡| 亚洲视频精品| 欧美 日韩 国产精品免费观看| 欧美一区亚洲一区| 欧美日韩一区二区欧美激情| 香蕉久久夜色精品国产使用方法| 欧美激情综合五月色丁香| 一本一本久久a久久精品牛牛影视| 欧美中文在线免费| 久久精品国亚洲| 国产欧美一区二区精品性色| 久久视频在线视频| 国产欧美一区二区三区视频| 一本久道久久久| 亚洲毛片av在线| 午夜电影亚洲| 亚洲国产一区二区精品专区| 久久精品成人欧美大片古装| 亚洲毛片一区| 欧美激情第六页| 亚洲国产岛国毛片在线| 亚洲人成人一区二区在线观看| 久热精品视频在线观看| 亚洲美女网站| 欧美日韩精品系列| 一本色道久久综合亚洲精品小说 | 中文国产一区| 国产精品男女猛烈高潮激情| 亚洲视频狠狠| 久久久久久午夜| 欧美精品在线一区| 在线综合亚洲欧美在线视频| 亚洲欧美日韩精品在线| 国产婷婷精品| 99精品国产福利在线观看免费 | 午夜精品久久久久久久久久久久久| 国产精品久久久久影院亚瑟 | 9i看片成人免费高清| 一区二区三区高清| 久久免费国产精品1| 香蕉久久一区二区不卡无毒影院| 国产视频精品va久久久久久| 久久综合中文| 在线一区免费观看| 久久人人97超碰人人澡爱香蕉| 在线观看日韩av| 欧美日韩亚洲一区二区三区在线观看 | 亚洲国产精品va在线看黑人| 国内外成人在线| 欧美激情一区二区三区不卡| 亚洲五月六月| 欧美久久在线| 欧美一区二区三区播放老司机| 亚洲制服少妇| 亚洲电影天堂av| 国产精品久久一区主播| 久久久精彩视频| 老司机亚洲精品| 亚洲夜间福利| 亚洲成色www久久网站| 欧美日韩亚洲一区二区| 久久亚洲精品网站| 亚洲欧美中文日韩在线| 亚洲国产精品一区制服丝袜| 久久久青草青青国产亚洲免观| 一区二区三区偷拍| 激情亚洲网站| 国产欧美一区二区色老头| 欧美精品三级日韩久久| 久久精品视频导航| 亚洲女与黑人做爰| 日韩网站在线看片你懂的| 毛片一区二区三区| 午夜亚洲视频| 亚洲一区二区视频| 日韩亚洲在线| 91久久精品一区二区别| 国产欧美视频一区二区三区| 欧美性理论片在线观看片免费| 麻豆精品视频在线观看| 亚洲欧洲美洲综合色网| 亚洲社区在线观看| 亚洲精品国产拍免费91在线| 韩国av一区二区三区| 国产精品中文字幕欧美| 国产精品乱人伦一区二区| 欧美日韩在线第一页| 欧美精品一卡二卡| 欧美成人一区二区三区在线观看 | 欧美高清免费| 欧美jizzhd精品欧美喷水 | 亚洲人成精品久久久久| 夜夜夜久久久| 亚洲精选中文字幕| 亚洲国产精品va在线看黑人| 欧美精品播放| 欧美精品色网| 国产精品扒开腿爽爽爽视频| 欧美日韩1区2区3区| 欧美日韩国产综合网| 欧美视频福利| 久久夜精品va视频免费观看| 久久天堂成人| 欧美成人精品在线播放| 欧美成人免费在线视频| 欧美丰满少妇xxxbbb| 欧美日韩国产在线播放| 欧美日韩一区二区三区在线观看免| 欧美日韩日日骚| 国产精品专区一| 在线观看欧美| 国产精品99久久久久久www| 午夜精品三级视频福利| 久久久久久自在自线| 欧美大片在线看免费观看| 亚洲国产精品国自产拍av秋霞| 亚洲精品乱码久久久久久日本蜜臀| 日韩午夜高潮| 欧美专区18| 欧美精品日韩精品| 国产嫩草影院久久久久| 在线观看视频免费一区二区三区| 亚洲啪啪91| 亚洲欧美日韩精品久久久久| 久热精品视频在线观看一区| 亚洲激情一区二区| 亚洲综合首页| 欧美成人亚洲成人| 国产精品入口尤物| 国产精品久久久久aaaa九色| 国产在线观看精品一区二区三区| 亚洲经典一区| 欧美在线观看日本一区| 亚洲国产专区校园欧美| 亚洲欧美日韩网| 欧美精品乱码久久久久久按摩| 国产欧美一区二区精品秋霞影院| 亚洲国产婷婷综合在线精品| 性欧美在线看片a免费观看| 欧美国产另类| 欧美在线综合| 国产精品国产三级国产aⅴ9色| 狠狠久久亚洲欧美专区| 亚洲午夜黄色| 亚洲国产精彩中文乱码av在线播放| 亚洲天堂视频在线观看| 欧美不卡一卡二卡免费版| 国产在线欧美日韩| 亚洲在线观看| 亚洲精品免费网站| 久久综合伊人77777蜜臀|