dothikoのカクカクワールド2D REBOOT

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか色々。

SWIGとnumpyについて(ImportErrorとセグメンテーションフォールト)

何か「ハリーポッターと魔法のナントカ」みたいなタイトル…

それはともかくSWIGとnumpyでハマってしまったので備忘録的にメモ。

現象としては

  • hppでNO_IMPORT_ARRAYを定義して#include <numpy/arrayobject.h>すると、.pyファイルでSWIGモジュールをインポートした時点でimporterror (undefined symbol: PyArray_API)が起きる。
  • NO_IMPORT_ARRAYを定義しないと、 cppでPyArray_ZEROS()を呼んだところでセグフォが起きる。

苦しんだのですが調べていてようやくわかりました。 基本的に

PY_ARRAY_UNIQUE_SYMBOL

が必要。

  • .iファイルのinit節でimport_array();呼び出し
%init %{
import_array();
%}
  • PY_ARRAY_UNIQUE_SYMBOLをdefineする共通のヘッダファイルを作成
#ifndef COMMON_HPP
#define COMMON_HPP

#define PY_ARRAY_UNIQUE_SYMBOL mytest_array_API

#endif

(↑基本的にmypaintのcommon.hppのパクリ)

  • このcommon.hppを、すべてのヘッダファイルで#include
  • ラッパー用ヘッダでのみNO_IMPORT_ARRAYを定義せず、その他の自作ヘッダではすべて#include <numpy/arrayobject.h>前にNO_IMPORT_ARRAYをdefineする。
  • NO_IMPORT_ARRAYを定義せずに#include “common.hpp"してあると、その都度シンボルが作られるらしくビルドエラーになる

これで、ImportErrorもビルドエラーもセグフォも起きなくなりました。

ところで統合開発環境のPyCharmを試してみたのですがこれは凄いですね。MyPaintも楽々走るしブレークポイントも普通に置けて(当然か…)これヤバイよ!と思いましたが、唯一悲しいのが起動速度の遅さ…まぁ、いいか。まだ、あんまり使ってないのですが。 ああ、あとちょっともっさり気味かもですが、これはまぁ機能の高さとおそらくpythonで書かれてる点からして仕方ないかも。