はじめに
Windowsプログラミングでは、Visual BasicスタイルとC言語スタイルの文字列の変換に混乱してしまうことがある。この変換自体はそれほど難しくはない。難しいのは、変換の細かい決まりを覚えておくことだ。一般的によく行われる処理ではない上に、MSDNには膨大な量のドキュメントがあるので、わからないことがあっても簡単には答えを見つけられない。しかし最も困るのは、型キャストを実行してコンパイルも正常にできたのに、プログラムが思いどおりに動作しないときだ。この場合コードはきちんと動作しないし、バグの原因を見つけ出すのも困難である。
この問題を何度か経験してみると、まず文字列変換が正しくできているかどうかを確認することが重要だとわかるはずだ。C文字列は、NULL文字で終了する文字配列で、一方のVisual Basic文字列は、先頭にその文字列の長さの情報を含んでいる(VB文字列は自身の長さを認識している)。さらに、すべてのVB文字列はUnicodeである(1文字につき16ビット)。
文字列の型
次の場合は、BSTR/C文字列の変換が必要である。
- C/C++でCOMプログラミングを行っている場合
- 複数言語のアプリケーション(Visual BasicアプリケーションからアクセスされるC++ DLLなど)を書いている場合
C言語の文字列の型とクラス
ここでは、次のC/MFC/ATL文字列型を取り上げる。
文字列の型 | 説明 |
char/wchar/TCHAR |
ANSIおよびUnicode用のC文字列 |
CString |
C文字列用のC++/MFCクラスラッパー |
BSTR |
Visual Basic文字列型 |
_bstr_t |
Visual Basic文字列型用のC++クラスラッパー |
CComBSTR |
Visual Basic文字列型用のもう1つのC++クラスラッパー(主にATLコードで使用) |
デモプロジェクト
このデモプロジェクトは、MFCダイアログベースのアプリケーションに各種の変換を実行するボタンを追加しただけのものだ。これはVC++ 6.0で作成した。参考までに、このプロジェクトで使用したサポート関数を紹介しておく。
BSTR GetBSTR() { _bstr_t bstr1(_T("This is the test string.")); BSTR bstr; bstr = bstr1.copy(); return bstr; } CComBSTR GetComBSTR() { CComBSTR bstr("This is the test string."); return bstr; } void CVbsDlg::ShowBSTR(BSTR bstr) { _bstr_t bstrStart(bstr); CString s; s.Format(_T("%s"), (LPCTSTR)bstrStart); AfxMessageBox(s); }
変換
では、具体的なコードを見ていこう。以降では、各種の変換テクニックを紹介する。
1. BSTRから_bstr_tへの変換
// BSTR to _bst_t BSTR bstrStart = GetBSTR(); // use the constructor _bstr_t bstrFinal(bstrStart); ShowBSTR(bstrFinal); // Use the = operator bstrFinal = bstrStart; ShowBSTR(bstrFinal);
2. _bstr_tからBSTRへの変換
_bstr_tクラスからBSTRを入手できる。
// _bstr_t to BSTR _bstr_t bstrStart(_T("This is the test string.")); BSTR bstrFinish; // use _bstr_t::copy member function bstrFinish = bstrStart.copy(); ShowBSTR(bstrFinish); // use = operator bstrFinish = bstrStart; ShowBSTR(bstrFinish);
3. CComBSTRからBSTRへの変換
CComBSTRクラスからBSTRを入手できる。
// CComBSTR to BSTR CComBSTR bstrStart(_T("This is the test string.")); BSTR bstrFinish; // use the = operator bstrFinish = bstrStart; ShowBSTR(bstrFinish); // use the Copy member function bstrFinish = bstrStart.Copy(); ShowBSTR(bstrFinish);
4. _bstr_tからCComBSTRへの変換
// _bstr_t to CComBSTR _bstr_t bstrStart(_T("This is the test string.")); CComBSTR bstrFinish; bstrFinish.AppendBSTR(bstrStart); ShowBSTR(bstrFinish);
5. BSTRからC文字列への変換
(注:Unicodeでのみ変換可能)
// BSTR to C String BSTR bstrStart; bstrStart = GetBSTR(); TCHAR szFinal[255]; // direct conversion from BSTR to LPCTSTR only works // in Unicode _stprintf(szFinal, _T("%s"), (LPCTSTR)bstrStart); AfxMessageBox(szFinal); _bstr_t bstrIntermediate(bstrStart); // convert to // _bstr_t CString strFinal; // you have to go through _bstr_t to have it work in ANSI // and Unicode _stprintf(szFinal, _T("%s"), (LPCTSTR)bstrIntermediate); // Or, using MFC strFinal.Format(_T("%s"), (LPCTSTR)bstrIntermediate); AfxMessageBox(strFinal);
6. _bstr_tからC文字列への変換
(この方法はANSIとUnicodeの両方で有効)
_bstr_t bstrStart(_T("This is the test string.")); TCHAR szFinal[255]; _stprintf(szFinal, _T("%s"), (LPCTSTR)bstrStart); AfxMessageBox(szFinal);
7. CComBSTRからLPCTSTRへの変換
(不可能。_bstr_tを経由する必要あり)
// CComBSTR to C String CComBSTR bstrStart("This is the test string."); _bstr_t bstrIntermediate(bstrStart); TCHAR szFinal[255]; _stprintf(szFinal, _T("%s"), (LPCTSTR)bstrIntermediate); AfxMessageBox(szFinal);
8. LPCTSTRから_bstr_tへの変換
コンストラクタまたは=演算子を使用。
// LPCTSTR to _bstr_t LPCTSTR szStart = _T("This is the text string"); // Use the constructor _bstr_t bstrFinal(szStart); ShowBSTR(bstrFinal); // or use = operator bstrFinal = szStart; ShowBSTR(bstrFinal);
9. LPCTSTRからCComBSTRへの変換
コンストラクタまたはCComBSTR::Append
関数を使用。
// LPCTSTR to CComBSTR // Use a constructor LPCTSTR szStart = _T("This is the text string"); // Use the constructor CComBSTR bstrFinal(szStart); ShowBSTR(bstrFinal); // Or use the Append function bstrFinal.Empty(); bstrFinal.Append(szStart); ShowBSTR(bstrFinal);
ここで紹介した変換テクニックは、全てデモプロジェクトで動作確認済みである。他のテクニックを試したい人は、デモプロジェクトをダウンロードして修正するとよい。
間違いがあったらぜひご報告いただきたい。