LoginSignup
7
6

More than 5 years have passed since last update.

Boost.pythonをhomebrewで導入

Last updated at Posted at 2016-02-06

Boost.pythonを試してみようとhomebrewで導入してみたところ、少々ハマりましたのでメモっておきます。

環境

  • OS X El Capitan(10.11.3)
  • Python 2.7.11 (homebrew)
  • boost 1.59 (homebrew)
  • boost-python 1.59 (homebrew)

使用例(C++)

c++の自乗を返す関数をpythonから呼んでみます。

hello_ext.cpp
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>

int square(int a)
{
    return a*a;
}

BOOST_PYTHON_MODULE(hello_ext)
{
    using namespace boost::python;
    def("square",square);
}

hello_ext.soをビルドするためのMakefileです。

all: hello_ext.so

CC = g++

FRAMEWORK_PATH=/usr/local/opt/python/Frameworks
INCLUDE_PATH=$(FRAMEWORK_PATH)/Python.framework/Versions/2.7/include/python2.7

hello_ext.o: hello_ext.cpp
    $(CC) -Wall -O2 -fPIC -c $< -I$(INCLUDE_PATH)

hello_ext.so: hello_ext.o
    $(CC) -shared  -o $@ $< -lboost_python -F$(FRAMEWORK_PATH) -framework Python

pythonの呼び出し側です。

hello.py
#!/usr/bin/env python
import hello_ext
print hello_ext.square(2)

ビルドと実行結果です。

$ make
g++ -shared  -o hello_ext.so -I/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/include/python2.7 hello_ext.o -lboost_python -F/usr/local/opt/python/Frameworks -framework Python
$ python hello.py
4

なるほど、昔ながらのPython拡張に比べてコードがすっきりしてよいですね。

使用例(Objective-C++)

既存のフレームワークを使いたいなどの理由で、Objective-Cを混在させるにはObjective-C++を使うといけますね。下記をhello_ext.mmとして作成します。

#include <boost/python/module.hpp>
#include <boost/python/def.hpp>

#import <Foundation/Foundation.h>

int square(int a)
{
    return a*a;
}

void nslog(void)
{
    NSLog(@"Hello");
}

BOOST_PYTHON_MODULE(hello_ext)
{
    using namespace boost::python;
    def("square",square);
    def("nslog",nslog);
}

Makefileは下記です。コンパイル時には-x objective-c++をつけ、リンク時にはフレームワークのパスとフレームワーク名をつけます。

all: hello_ext.so

CC =clang++

FRAMEWORK_PATH=/usr/local/opt/python/Frameworks
INCLUDE_PATH=$(FRAMEWORK_PATH)/Python.framework/Versions/2.7/include/python2.7
FRAMEWORK_PATH2=/System/Library/Frameworks

STD_CPP_PATH = /usr/include/c++/4.2.1/

FRAMEWORK_OPTIONS=-F$(FRAMEWORK_PATH) -framework Python -F$(FRAMEWORK_PATH2) -framework Foundation

hello_ext.o: hello_ext.mm
    $(CC) -x objective-c++ -Wall -O2 -fPIC -c $< -I$(INCLUDE_PATH) -I$(STD_CPP_PATH)

hello_ext.so: hello_ext.o
    $(CC) -shared -o $@  $< -lboost_python $(FRAMEWORK_OPTIONS)

.PHONY: clean
clean:
    rm *.so *.o

下記で呼び出せます。

import hello_ext

hello_ext.nslog()
print hello_ext.square(2)

実行結果は下記です。

2017-04-09 11:45:29.818 Python[7710:333116] Hello
4

ハマった点と解決までの経緯

まず公式チュートリアルはbjamを使えと書いてあります。bjamはhomebrewの boost-buildを入れるとインストールできますが、Jamfileとやらのパスを指定せよといわれ、homebrewでのインストール先がわからず断念しました。

次にBoost.Python の機能をざっと紹介してみるなどの先人に習ってg++でビルドをしてみましたが、引数の受け渡しをしようとした時点で、

Segmentation fault: 11

だの、

Fatal Python error: PyEval_SaveThread: NULL tstate

だのいわれて散々でした。

後者のエラーメッセージが検索に引っ掛かり、StackOverFlowの記事にたどり着きました。

だいたいこういうのは複数のバージョンの python が混在してるときじゃね?
otool -Lとかで依存関係を見てみたら;)

とのコメントがまさにビンゴ。確かにOSXネイティブなパスとhomebrewのパスが混在していました。

ということで、-F オプションをつけてフレームワークのパスを OSX ネイティブのものではなく homebrew のものに置き換えることで解決しました。

-Fオプションには man ld でたどり着きました。恥ずかしながら -framework オプションも理解しておらず。勉強不足でしたがどうにかたどり着きました。

参考リンク

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6