本日は
先日書きました
C/C++ から Cython によって生成されたコードを呼び出す(Windows版)
のMac版をやってみましょう.Pythonは pyenv でのどれかの環境を用いているものとします.
Cythonコードを用意
頂点構造体を定義して座標を2倍にした頂点構造体を返す関数を作ってみましょう.
cdef public struct Point:
double x
double y
cdef public Point DoubleCoord(Point p):
cdef Point q
q.x=2*p.x
q.y=2*p.y
return q
setup.py
も用意しましょう.
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize("cytest.pyx"))
コード生成
$ python setup.py build_ext --inplace
こうすることで cytest.h
cytest.c
が生成されるはずです.
呼び出しコード作成
下のようにコードを書いてみましょう.
#include <stdio.h>
#include <Python.h>
#include "cytest.h"
int main(int argc, char const *argv[])
{
Py_Initialize();
struct Point p;
p.x=3.0;
p.y=4.0;
struct Point q = DoubleCoord(p);
printf("Hello\n");
printf("q.x=%f,q.y=%f\n",q.x,q.y);
Py_Finalize();
/* code */
return 0;
}
ここで注意したいのが cytest.h
をインクルードする前に Python.h
をインクルードしないと
error: unknown type name 'PyMODINIT_FUNC'
と怒られちゃいます.
レッツビルドの前に
ここでは pyenv 環境での 3.5.4 の場合で試してみます.
$ pyenv global
3.5.4
まず Python.h
がどこにあるのかを確かめないといけません.
結論としては
$HOME/.pyenv/versions/3.5.4/include/python3.5m
となり, Finder で眺めるとヘッダーファイルが並んでいると思います.
リンかーがライブラリを探すので場所を教えないといけません.include
と同階層にlib
というのがあるのでここを眺めましょう.
見つかりましたね.
レッツビルド
を参考に恐る恐る書いてみましょう.
gcc -Wall -I $HOME/.pyenv/versions/3.5.4/include/python3.5m -L $HOME/.pyenv/versions/3.5.4/lib -lpython3.5m call.c cytest.c
そうすると実行ファイルa.out
ができるので
$ ./a.out
Hello
q.x=6.000000,q.y=8.000000
と頂点座標が2倍になる様子が確認されました.
これでC/C++からPythonを呼び出せますし, 逆もCythonを介して呼び出せるのでどの方向からでも連携できるようになりました.