TN059: MFC MBCS/Unicode 変換マクロを使用します。

このノートでは、AFXPRIV で定義されている MBCS/Unicode 変換マクロを使用する方法について説明します。H. これらのマクロは、アプリケーションのお得な情報直接、OLE api またはいくつかの理由には、多くの場合必要とする場合 Unicode と MBCS の間を変換する最も便利です。

概要

MFC 3.x では、特別な DLL を使用した (MFCANS32。DLL) OLE インターフェイスが呼び出されたときに Unicode と MBCS の間を自動的に変換します。この DLL の OLE Api とインターフェイス MBCS、あたかも彼らは常に Unicode がも OLE アプリケーションを許可、ほぼ透明層だった (Macintosh の場合を除く)。このレイヤーが便利だった間、すぐに Win16 から Win32 に移植するアプリケーションを許可 (MFC、Microsoft Word、Microsoft Excel、および VBA ではいくつかのこの技術を使用する Microsoft アプリケーション)、大幅なパフォーマンスもヒットします。このため、MFC 4.x はこの DLL を使用しないし、代わりに直接、Unicode OLE インターフェイスには語る。これを行うには、MFC は MBCS に Unicode OLE インターフェイスへの呼び出しを行うときに変換する必要があるし、多くの OLE インターフェイスを実装するときに MBCS に Unicode から変換する必要があります。これは効率的かつ簡単に処理するには、マクロのこの変換を簡単に作成されました。

このような一連のマクロを作成するには、最大のハードルの 1 つはメモリの割り当てです。場所に、文字列を変換できないため、変換の結果を保持するために新しいメモリを割り当てる必要があります。これは、コードは次のように行われていること:

//私たちは lpszA の MBCS 文字列を変換します。int nLen MultiByteToWideChar (CP_ACP、0、lpszA、-1 NULL, NULL); =LPWSTR lpszW 新しい WCHAR [nLen]; =MultiByteToWideChar (CP_ACP、0、lpszA、-1、lpszW、nLen);//ここで OLE を呼び出すを使用pI-gt;SomeFunctionThatNeedsUnicode(lpszW);//文字列を無料lpszW を削除します。(&G)

このアプローチは多くの問題としては。主な問題は、それ多くの記述、テスト、およびデバッグするためのコードです。何かは、単純な関数呼び出しが、今はもっと複雑です。また、ある重要なランタイム オーバーヘッドそう。メモリがヒープに割り当て、変換を行うたびに解放する必要があります。最後に、上記のコードが適切な必要と #ifdefs (これは、場所を取るには、この変換を必要としない) Unicode と Macintosh のビルドを追加。

私たちを思いついたソリューションは、ソース コード、1) マスクとの違い、さまざまなプラットフォーム、2) 使用、効率的なメモリ割り当てスキームと 3) は、既存に挿入する簡単なマクロを作成します。定義の 1 つの例はここにあります。:

# define A2W(lpa) (\特価;((LPCSTR) lpa = = NULL) ですか?NULL: (\_convert (strlen (lpa) +1) = \AfxA2WHelper((LPWSTR) alloca(_convert*2)、lpa _convert) \)\)(&N)

この上記のコードの代わりにマクロをして、物事は非常に簡単:

//ここで OLE を呼び出すを使用USES_CONVERSION;pI-gt;SomeFunctionThatNeedsUnicode(T2OLE(lpszA))(&G)

ここで変換が必要です。 が、マクロを使用して簡単かつ効果的な余分な呼び出しです。

各マクロの実装では、_alloca() 関数を使用して、ヒープではなくスタックからメモリを割り当てるします。スタックからメモリを割り当て、ヒープ上のメモリを割り当てるよりもはるかに高速ですし、関数が終了したときに、メモリが自動的に解放されます。さらに、マクロが MultiByteToWideChar ( WideCharToMultiByte) の呼び出しを避ける 1 つ以上の時間。これは必要であるより少しより多くのメモリを割り当てることによって行われます。私たちは MBC で最も 1 つWCHARに変換することや各WCHARに我々 の 2 つの MBC バイトの最大が知っています。常に十分な必要は少し以上の割り当てで 2 番目の呼び出しは、変換処理に変換関数の呼び出しを回避できます。ヘルパー関数AfxA2Whelperの呼び出し (直接MultiByteToWideCharと呼ばれる場合この小さいコードより結果)、変換を実行するために行う必要があります引数プッシュの数が減少します。

スペースをマクロを格納するために、一時的な長さ、それ変換マクロを使用してこれは、各関数では _convert と呼ばれるローカル変数を宣言する必要があります。これは、上記の例のようにUSES_CONVERSIONマクロを呼び出すことによって行われます。

汎用変換マクロおよび OLE の特定のマクロの両方があります。これら 2 つの異なるマクロ セットについて説明します。すべてのマクロは AFXPRIV に存在します。H。

汎用変換マクロ

汎用変換マクロは、基になる機構を形成します。マクロの例、前のセクションでは、A2W を示す実装など「汎用の」の 1 つのマクロです。具体的には、OLE の関係はありません。一般的なマクロの設定次のとおりです。:

 A2CW (LPCSTR) gt;(LPCWSTR)A2W (LPCSTR) - > (LPWSTR)W2CA (LPCWSTR) - > (LPCSTR)W2A (LPCWSTR) - > (LPSTR)

テキストの変換を行う、ほかマクロもあるし、文字列TEXTMETRICDEVMODEBSTROLE を変換するためのヘルパー関数を割り当ています。これらのマクロは、この議論の範囲を超えている-AFXPRIV を参照してください。これらのマクロの詳細については H。

OLE 変換マクロ

OLE 変換マクロは、 OLESTR文字の機能を処理するために特に設計されています。OLE ヘッダーを調べると、 LPCOLESTROLECHARの多くの参照が表示されます。これらの種類は、OLE インターフェイスは、プラットフォームに固有ではない方法で使用される文字の種類を参照する使用されます。Win16 と Macintosh プラットフォームのchar 型WCHAR win32 OLECHARマップ。

各変換のようなマクロがあるが#ifdefディレクティブの MFC コードを最小限に抑えるためには、OLE 文字列は関与しています。次のマクロが、最も一般的に使用されます。:

T2COLE (LPCTSTR) gt;(LPCOLESTR)T2OLE (LPCTSTR) - > (LPOLESTR)OLE2CT (LPCOLESTR) - > (LPCTSTR)OLE2T (LPCOLESTR) - > (LPCSTR)

再びTEXTMETRICを行うのと同様のマクロは、 DEVMODE BSTR、OLE 文字列を割り当ています。AFXPRIV を参照してください。H の詳細。

その他の考慮事項

マクロは、タイトなループで使用しないでください。たとえば、あなたは、次のようなコードを記述したくはないです。:

void BadIterateCode(LPCTSTR lpsz){USES_CONVERSION;(int ii = 0; ii lt; 10000; ii + +)pI - > SomeMethod (ii、T2COLE(lpsz));}

上記のコード mb の文字列の内容に応じてスタックにメモリを割り当てる可能性があります lpsz です ! 特価;また、ループの各繰り返しの文字列を変換するには時間がかかります。代わりにこのような定数の変換は、ループの外に移動します。(&N):

void MuchBetterIterateCode(LPCTSTR lpsz){USES_CONVERSION;LPCOLESTR lpszT = T2COLE(lpsz);(int ii = 0; ii lt; 10000; ii + +)pI - > SomeMethod (ii、lpszT);}

文字列が定数でない場合は、[メソッドの呼び出しを関数にカプセル化します。これは、変換バッファーするたびに解放することができます。たとえば:

void CallSomeMethod (int ii、LPCTSTR lpsz){USES_CONVERSION;pI-gt;SomeMethod (ii、T2COLE(lpsz));}void MuchBetterIterateCode2 (LPCTSTR ※ lpszArray){(int ii = 0; ii < 10000; ii + +)CallSomeMethod (ii、lpszArray[ii]);}

戻り値を返す前に、のデータのコピーを作成意味しない限りは、マクロのいずれかの結果を返します。たとえば、このコードが悪いです。:

LPTSTR BadConvert(ISomeInterface* pI){USES_CONVERSION;LPOLESTR lpsz = NULL;pI-gt;GetFileName(&lpsz);LPTSTR lpszT = OLE2T(lpsz);CoMemFree(lpsz);lpszT を返す;・ ・悪い !alloca メモリを返す}

上記のコードを修正することができる何かには、値をコピー戻り値を変更します:

CString BetterConvert(ISomeInterface* pI){USES_CONVERSION;LPOLESTR lpsz = NULL;pI-gt;GetFileName(&lpsz);LPTSTR lpszT = OLE2T(lpsz);CoMemFree(lpsz);lpszT を返す;//CString にコピー}

マクロを使用して簡単にされをコードに挿入する簡単が上記の注意事項から言うことができる、それらを使用する場合は注意する必要があります。

番号順テクニカル ノート|nbsp;カテゴリ別テクニカル ノート(&N)

Index