SWIGでPythonラッパを書いてみる
何度も挫折したSWIGにチャレンジ.今回はPythonラッパを書くことに成功した,やほーい!以下,自分用メモ
Cコードの作成
#include <stdio.h> void print_hoge (int n) { int i; for (i = 0; i < n; i++) { printf("hoge\n"); } }
.iファイルの作成
こんな感じのexample.iファイルを作成する.ラッパから利用したいファイルをexternする.
%module example %{ /* Write include header (Optional) */ /* #include "example.h" */ %} extern void print_hoge (int n);
ラッパの作成
% swig -python example.i % gcc -c example.c % gcc -c example_wrap.c % gcc -shared example.o example_wrap.o -o _example.so
これで,_example.soが作成される.
利用方法
% python >>> import example >>> example.print_hoge(5) hoge hoge hoge hoge hoge
C構造体の利用方法
少しはまったのでメモ.例えば以下のようなコードを用意
- hoge.c
#include <stdio.h> #include "hoge.h" Data * data_new (int id, char *name) { Data *d = malloc(sizeof(Data)); if (d == NULL) { perror("malloc"); exit(1); } d->id = id; d->name = malloc(sizeof(char) * (strlen(name) + 1)); if (d->name == NULL) { perror("malloc"); exit(1); } strcpy(d->name, name); return d; } void data_print (Data *d) { printf("id=%d\n", d->id); printf("name=%s\n", d->name); }
- hoge.h
typedef struct data_t { int id; char *name; } Data;
さっきと同様の手順でラッパーを作ればよい.test.iの書き方に注意
%module test %{ #include "test.h" %} extern Data *data_new (int i, char *n); extern void data_print (Data *d);
この場合だと,構造体の各要素にアクセスすることができない.
最初の%{%}に囲まれた部分については,ラッパークラスは知らないものとされるらしい.
>>> import test >>> d = test.data_new(4649, "sleepy_yoshi") >>> d.id = 1234 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'PySwigObject' object has only read-only attributes (assign to .id)
というわけで,ラッパークラスにも内容を教えてあげる必要がある.
%module test %{ #include "test.h" %} /* #include "test.h"ではうまくいかなかった */ typedef struct data_t { int id; char *name; } Data; extern Data *data_new (int i, char *n); extern void data_print (Data *d);
なぜか,#includeではうまくいかなかったので,ベタ書きした.
>>> import test >>> d = test.data_new(4649, "sleepy_yoshi") >>> d.id = 1234 >>> test.data_print(d) id=1234 name=sleepy_yoshi
うまくアクセスできるようになった.いかんせん,Pythonをほとんど使ったことがないので,test.xxxというようにモジュール名を書くのがだるいなぁ,とか
クラス定義などどうするのかということがよくわかっていない.
とりわけ速いわけでもないし,とりわけPythonでしかできないこともなかったので,とくに使ってこなかったけれど,ラッパーが作りやすい(正確には,自分がPythonしか知らない)ので,これからしばらくPythonを書こうかな.