boost.pythonでC++からpythonの関数オブジェクトをコールする。

boost.pythonのFAQにはこんなの
http://www.boost.org/doc/libs/1_41_0/libs/python/doc/v2/faq.html#funcptr
が載っているがそりゃ無理だろうとw


そうじゃなくて、普通にpythonのオブジェクトを取り出してコールする方法について。

#include <boost/python.hpp>
#include <iostream>

void pyExec(PyObject *func)
{
  std::cout << "## pyExec ##" << std::endl;
  if (PyCallable_Check(func)) {
    PyEval_CallObject(func, NULL);
  }
  else{
    std::cout << "not callable" << std::endl;
  }
}

BOOST_PYTHON_MODULE(functor)
{
  using namespace boost::python;

  def("call", pyExec);
}

テスト用のスクリプト

import functor # 上で作ったモジュール
import sys

print dir(functor)

functor.call("aaa")

functor.call(lambda : sys.stdout.write('lambda\n'))

def hoge():
    print "hoge"

functor.call(hoge)

出力

['__doc__', '__file__', '__name__', '__package__', 'call']
## pyExec ##
not callable
## pyExec ##
lambda
## pyExec ##
hoge

目的達成。

次の段階として渡された呼び出し可能なオブジェクトを変数として保持するという問題があるがそれは、
http://www.python.jp/doc/2.5/ext/callingPython.html
を読めば問題ない。
Py_XINCREFとPy_XDECREFでリファレンスカウントの面倒を見てやること。