mlang.dllのConvertINetString関数を使った文字コードを変換するサンプル
C++ Builder 2009を使いました。
_TCHARのマップ先は「wchar_t」に設定しています。
本題に入る前に前準備として、DLLのリソース管理クラス(RAII)を用意します。
このクラスTDllはデストラクタでFreeLibraryを行うので、DLLのハンドルの解放のし忘れを防ぐことができます。
/**
* DLLのリソース管理(RAII)
*/
class TDll
{
public:
TDll(const UnicodeString& DllName)
{
FDll = LoadLibrary(DllName.c_str());
}
~TDll()
{
if (!FDll) FreeLibrary(FDll);
}
operator bool() const
{
return FDll;
}
operator HMODULE() const
{
return FDll;
}
private:
HMODULE FDll;
};
ConvertINetStringのtypedefを定義します。
なくてもいいのですが、あるとソースコートが読みやすくなります。
typedef HRESULT WINAPI (*TConvertINetString)(LPDWORD lpdwMode, DWORD dwSrcEncoding, DWORD dwDstEncoding, LPCSTR lpSrcStr, LPINT lpnSrcSize, LPBYTE lpDstStr, LPINT lpnDstSize);
mlang.dllを読み込みます。
読み込みに失敗したときはエラーメッセージを表示します。
TDll dll("mlang.dll");
if (!dll)
{
std::puts("DLLの読み込みに失敗しました。");
return 0;
}
ConvertINetString関数のアドレスを取得します。
失敗したときはエラーメッセージを表示します。
//関数のアドレスの取得
FARPROC proc = GetProcAddress(dll, "ConvertINetString");
if (!proc)
{
std::puts("関数のアドレスの取得に失敗しました。");
return 0;
}
TConvertINetString ConvertINetString = reinterpret_cast<TConvertINetString>(proc);
ConvertINetString関数に渡す変数を用意します。
今回のサンプルではShift_JISをEUC-JPに変換します。
DWORD mode = 0;
AnsiStringT<932> sjis = "あいうえおかきくけこさしすせそたちつてと";
int sjisLen = sjis.Length();
int eucLen = sjisLen * 2 + 1;
boost::scoped_array<char> euc(new char[eucLen]);
ZeroMemory(euc.get(), eucLen);
ConvertINetString関数を呼び出して変換します。
変換に失敗したときはエラーメッセージを表示します。
//変換
HRESULT result = ConvertINetString(&mode, 932, 51932, sjis.c_str(), &sjisLen, euc.get(), &eucLen);
//変換結果の検証
if (result != S_OK || eucLen == 0)
{
std::puts("変換に失敗しました。");
return 0;
}
というのが一連の流れになります。
以下のコードはShift_JIS(コードページ932)の文字列をEUC-JP(コードページ51932)に変換します。
#include <tchar.h>
#include <iostream>
#include <memory>
#include <boost/scoped_array.hpp>
int _tmain(int argc, _TCHAR* argv[])
{
typedef HRESULT WINAPI (*TConvertINetString)(LPDWORD lpdwMode, DWORD dwSrcEncoding, DWORD dwDstEncoding, LPCSTR lpSrcStr, LPINT lpnSrcSize, LPBYTE lpDstStr, LPINT lpnDstSize);
//DLLの読み込み
TDll dll("mlang.dll");
if (!dll)
{
std::puts("DLLの読み込みに失敗しました。");
return 0;
}
//関数のアドレスの取得
FARPROC proc = GetProcAddress(dll, "ConvertINetString");
if (!proc)
{
std::puts("関数のアドレスの取得に失敗しました。");
return 0;
}
TConvertINetString ConvertINetString = reinterpret_cast<TConvertINetString>(proc);
//変換準備
DWORD mode = 0;
AnsiStringT<932> sjis = "あいうえおかきくけこさしすせそたちつてと";
int sjisLen = sjis.Length();
int eucLen = sjisLen * 2 + 1;
boost::scoped_array<char> euc(new char[eucLen]);
ZeroMemory(euc.get(), eucLen);
//変換
HRESULT result = ConvertINetString(&mode, 932, 51932, sjis.c_str(), &sjisLen, euc.get(), &eucLen);
//変換結果の検証
if (result != S_OK || eucLen == 0)
{
std::puts("変換に失敗しました。");
return 0;
}
//ファイルに保存
std::unique_ptr<TFileStream> fs(new TFileStream("C:\\test.txt", fmCreate));
fs->WriteBuffer(euc.get(), eucLen);
return 0;
}