開発ノウハウ集 2012/12/18 hase wrote

呼び出しは下記では上手く行かなかった。

void CallbackFunc() {
	PyGILState_STATE state = PyGILState_Ensure();
	if (state == PyGILState_UNLOCKED)
		PyObject_CallObject(pyCallback, NULL);
	PyGILState_Release(state);
}

で上手く行った。

PyEval_InitThreads();

は最初にEPLoopInit()で呼び出しておく。

2012/12/18 mitake wrote

登録

下記の関数をPythonから呼べる形で作成します.

(独自関数をPythonから呼べるようにする方法についてはPythonからアプリケーションの関数を呼び出すを参照してください.

void SetCallbackFunc(PyObject* func) {
	if (!PyCallable_Check(func)) {
		PyErr_SetString(PyExc_TypeError, "parameter must be callable");
		return;
	}
	Py_XINCREF(func);
	Py_XDECREF(callbackFunc);	// 以前のコールバックを捨てる
	callbackFunc = func;		// 新たなコールバックを記憶
}

pythonプログラム側では以下のようにして登録します.

def callback():
	print("hoge")

# appはSetCallbackFunc関数をメンバに持つアプリケーション
app.SetCallbackFunc(callback)

呼び出し

登録されたコールバックをC++から呼び出す場合は以下のようにします.

void CallbackFunc() {
	if (callbackFunc != NULL) {
		PyEval_InitThreads();

		// GIL(Global Interpreter Lock) を取得する
		PyGILState_STATE state = PyGILState_Ensure();

		// コールバック関数を呼ぶ
		PyObject_CallObject(callbackFunc, NULL);

		// GILを解放する
		PyGILState_Release(state);
	}
}