以下是 ATL7.0 版 Marco、Class的命名規則
CSourceType2[C]DestinationType[EX]
以下是 ATL3.0 舊版 Marco的命名規則
SourceType2[C]DestinationType[EX]
SourceType or DestinationType包含了A, W, T, OLE可使用,Ex: A2W, W2T, T2OLE...
- 新舊版的命名規則差異只有開頭有沒有C,結果有沒有EX。新版的C開頭代表跟舊版的Marco不一樣,而是以Class去實作的。Ex: A2W, W2A是Marco,CA2W, CW2A則是Class。
- [C] : 中間的C可有可無,代表著DestinationType是否為 const 的字串。
- [EX] : 新版的EX表示,可指定Class所使用的Buffer size。Ex: CA2W<64>
既然有新版的,當然是用新的好啊,因為用舊版的在使用前,必須手動加一個Marco : USES_CONVERSION才能正常Work。舊版是吃stack的memory,一定要等function離開後才會release。
範例:
[錯誤!] 將ANSI的字串轉成Unicode字串
LPSTR name = "Falldog"; LPWSTR wstr = CA2W(name); //Use wstr....這樣子的寫法,在 ATL3.0 使用A2W是可以work的,但是在 ATL7.0 的版本中,CA2W是一個class,所以意義上會變得不太一樣。
將上面的範例做慢動作解析:
LPSTR name = "Falldog"; LPWSTR wstr; { CA2W temp(name); wstr = temp.operator LPWSTR(); } //Use wstr.... but memory stored in temp is destroyed...
//再把上面的有問題的地方轉成平常可能看到的畫面 LPWSTR my_func_CA2W( /*LPSTR ansi*/) { WCHAR* temp = L"Falldog"; return temp; } LPWSTR wstr = my_func_CA2W(); //Use wstr....下半部出現的問題是,當 my_func_CA2W 將 temp return 回來後,其實儲存字串內容的 memory 就已經被 release 掉了,所以當去 access wstr 時,就會有 exception 了。
而上半部跟下半部的問題是一樣的,當你 create 了一個CA2W的object,但是卻把它 assign 給一個 pointer,而 CA2W 的 life scope 在 assign 給 pointer 之後就結束了。當然使用者再使用 wstr 後,會出現 exception。
LPSTR name = "Falldog"; CA2W wstr(name); //Use wstr...
[正解2] 將ANSI的字串轉成Unicode字串 (只用一次,
LPSTR name = "Falldog"; wprintf( L"User Unicode Name=%s", CA2W(name) );
Reference : [MSDN] ATL and MFC String Conversion Macros
沒有留言:
張貼留言