wchar_t対応版libstdc++

昨日の続きです。
libstdc++のconfigureスクリプトを確認したところ、iconvとlanginfoが動かないと、wchar_t対応にならないようでした。
iconvはGNUのものを使ってもいいのですが、configureの要求するシンボル名と違うことと、実行ファイルを配布する際に別途dllが必要になることから、適当にでっち上げることにしました。

/* iconv.h */
#ifndef ICONV_H
#define ICONV_H

#include <stddef.h>

#if defined(__cplusplus)
extern "C" {
#endif

typedef int iconv_t;

iconv_t iconv_open(const char* tocode, const char* fromcode);

int iconv_close(iconv_t cd);

size_t iconv(iconv_t cd,
    char** inbuf, size_t* inbytesleft,
    char** outbuf, size_t* outbytesleft);

#if defined(__cplusplus)
} // extern "C"
#endif

#endif /* ICONV_H */
/* iconv.c */
#include "iconv.h"

iconv_t iconv_open(const char* tocode, const char* fromcode)
{
    return (iconv_t)-1;
}

int iconv_close(iconv_t cd)
{
    return 0;
}

size_t iconv(iconv_t cd,
    char** inbuf, size_t* inbytesleft,
    char** outbuf, size_t* outbytesleft)
{
    return (size_t)-1;
}
/* langinfo.h */
#ifndef LANGINFO_H
#define LANGINFO_H

#if defined(__cplusplus)
extern "C" {
#endif

typedef int nl_item;

char* nl_langinfo(nl_item item);

#if defined(__cplusplus)
} // extern "C"
#endif

#endif /* LANGINFO_H */
/* langinfo.c */
#include "langinfo.h"

char* nl_langinfo(nl_item item)
{
    return (char*)"";
}

すべてコンパイルとリンクを通すための空実装になっています。
実際には呼ばれないので、これで問題ありません。
これらを、MSYSから

gcc -c iconv.c langinfo.c
ar cr /mingw/lib/libiconv.a iconv.o langinfo.o
cp iconv.h langinfo.h /mingw/include/

として、libstdc++のconfigureをやり直すと、wchar_tサポートが有効になります。
libiconv.aにlanginfo.oを含めているのは、configureスクリプトがlibcとiconvしかリンクしないからです。


こうしてビルドしたlibstdc++を使って、次のプログラムを試してみました。

#include <clocale>
#include <iostream>

int main()
{
    std::setlocale(LC_ALL, "");
    std::wcout << L"\u3042\u3044\u3046\u3048\u304A" << std::endl;
}

結果、

あいうえお

を出力できました。
ワイド文字列とマルチバイト文字列の変換ははCの標準関数を使用する実装なので、setlocale()でCの大域ロケールを設定する必要があります。


Boost.Filesystemのwide_testも試してみましたが、問題なく動作しました。
そこそこ使えるのではないかと思います。