このBlogは移転しました。今後は aish.dev を御覧ください。

Pyrex 0.9.9の変更点

先日 Python拡張モジュール開発言語 Pyrex の 0.9.9がリリースされたが、このバージョンでは旧バージョンとは非互換となる変更が加えられており、注意が必要である。

例外処理の変更

Pyrex 0.9.9では、発生した例外が実行中のスレッドに保存されなくなり、sys.exc_info()等で例外を参照することができなくなってしまった。これまでは

try:
   raises_exc()
except:
   traceback.print_exc()

で正しくトレースバックを出力することができたが、0.9.9で同様の処理を行うには、以下のようにexcept ステートメントで明示的に例外を受け取らなければならない。exceptステートメントが修正され、トレースバックオブジェクトを受け取ることができるようになっている。

try:
    raises_exc()
except Exception, e, tb:
    traceback.print_exception(type(e), e, tb)

__new__()が使えなくなった

古いバージョンのPyrexではオブジェクトの初期化を__new__()メソッドでも行えたが、0.9.9では__new__()の使用が禁止された。代わりに __cinit__()を使用しなければならない。

整数値型変換の変更

同じ変換順位を持つ整数値の演算では、どちらかが unsigned であれば結果は unsigned となる。順位が異なる場合には、より高い順位の項と同じ型となる。

cintern()

これまでは

s = intern(string_obj)

でPyString_InternString()が呼び出されていたが、0.9.9ではこの変換が廃止された。0.9.9以降では、代わりに

s = cintern(string_obj)

を使用しなければならない。

C++サポート

非互換な修正ではなく新機能だが、0.9.9の目玉なので紹介しておく。

PyrexからC++のクラスを利用する機能が追加された。PyrexでC++のクラス

class Shrubbery {
public:
    Shrubbery();
    Shrubbery(float width);
    Shrubbery(float width, int price);
    float width;
    int height;
    void plant_with_rhododendrons(int howmany);
}


をPyrexから使用する場合、

cdef extern from "somewhere.h":
    cdef+ struct Shrubbery:
        __init__()
        __init__(float width)
        __init__(float width, int price)
        float width
        int height
        void plant_with_rhododendrons(int howmany)

のような定義を、定義ファイル(拡張子:*.pxd)に記述する。

この定義をC++の機能を利用するソースファイルは、通常のPyrexソースファイル(拡張子:*.pyx)ではなく、*.pyx+というファイル名でなければならないので注意。

クラスが継承関係を持つ場合、Pyrexで次のように定義できる。

cdef+ extern from "shrubbing.h":
    struct FancyShrubbery(Shrubbery):
        ....

C++オブジェクトの作成・削除は new/delで行う。

cdef Shrubbery *obj
obj = new Shrubbery(4.3, 800)
del obj

オーバロードされた関数がある場合、Pyrexではそれぞれの関数に別々の名前を指定して呼び出さなければならない。

cdef extern from "shrubbing.h":
    void build_with_width "build_shrubbery" (float width)
    void build_with_petunias "build_shrubbery" (int number_of_petunias)