irr::core::stringのラップ

Irrlichtはいい描画エンジンなのだが、なにもかもC++でやるとつらいのでスクリプト導入のターンとなるわけです。
そういうわけで、swigで半自動でCモジュールを作るのだがはまりポイントがある。
irr::core::stringであります。
以前、lua版作ったときも同じところではまった気がするが、今回はpython版。
以下、irrlichtのswigラップのirrString.hに関する部分を単体でビルドできるように試作したもの。

irr.i

%module "irr"

%{
#include "Irrlicht.h"
%}

// pythonのunicodeをwchar_t*として受け取る
%typemap(in) const wchar_t * const {
   $1 = PyUnicode_AS_UNICODE($input);
}

// irr::core::stringのコンストラクタがうまくいかないので生成用の関数
%inline %{
irr::core::stringc* strc(const char* const c){return new irr::core::stringc(c);}
irr::core::stringw* strw(const wchar_t* const c){return new irr::core::stringw(c);}
%}

// swigで生成されるirr_wrap.cppのコンパイル通すのに必要
%{
using namespace irr;
using namespace core;
%}

#pragma SWIG nowarn=362
#pragma SWIG nowarn=389

// コンパイル通すのに必要
//  error: call of overloaded 'string(long int&)' is ambiguous ...
%ignore irr::core::string::operator+=;

%include "irrString.h"
// テンプレート実体化
%template(irrStringC) irr::core::string<c8>;
//  Warning 490: Fragment 'SWIG_AsVal_wchar_t' not found
// に対応。よくわからない
// http://old.nabble.com/SWIG_AsVal_wchar_t-error-td4996377.html
%fragment("SWIG_AsVal_wchar_t", "header", fragment="<wchar.h>") {
    SWIGINTERN int SWIG_AsVal_wchar_t(PyObject* p, wchar_t* c) {
        return SWIG_OK;
    }
}
%fragment("SWIG_From_wchar_t", "header", fragment="<wchar.h>") {
    SWIGINTERNINLINE PyObject* SWIG_From_wchar_t(wchar_t c) {
        return SWIG_Py_Void();
    }
}
// テンプレート実体化
%template(irrStringW) irr::core::string<wchar_t>;
#!/usr/bin/env python

"""
setup.py file for SWIG example
"""

from distutils.core import setup, Extension

module_name='irr'

include_dirs=[
        '/irrlicht/include',
        ]

ex_module = Extension('_'+module_name,
        sources=[module_name+'.i'],
        swig_opts=['-I/irrlicht/include', '-c++'],
        include_dirs=include_dirs
        )

setup (name = module_name,
        version = '0.1',
        author      = "ousttrue",
        description = """irrlicht string test""",
        ext_modules = [ex_module],
        py_modules = [module_name],
        )

ビルド

> python setup.py build_ext --inplace

動作確認

sample.py

import irr
print irr.strc("hoge")
print irr.strw(u"hoge")

<irr.irrStringC; proxy of <Swig Object of type 'irr::core::stringc *' at 0x00535CB0> >
<irr.irrStringW; proxy of <Swig Object of type 'irr::core::string< wchar_t > *' at 0x00535CB0> >

あと、__str__を仕込めばよい感じになるんでないか。

参考

C#用にIrrlicht全体をラップしている