#pragma once #include "capnp/dynamic.h" #include #include "Python.h" class GILAcquire { public: GILAcquire() : gstate(PyGILState_Ensure()) {} ~GILAcquire() { PyGILState_Release(gstate); } PyGILState_STATE gstate; }; class GILRelease { public: GILRelease() { Py_UNBLOCK_THREADS } ~GILRelease() { Py_BLOCK_THREADS } PyThreadState *_save; // The macros above read/write from this variable }; ::kj::Promise convert_to_pypromise(capnp::RemotePromise & promise); inline ::kj::Promise convert_to_pypromise(kj::Promise & promise) { return promise.then([]() { GILAcquire gil; Py_INCREF( Py_None ); return Py_None; }); } template ::kj::Promise convert_to_voidpromise(kj::Promise & promise) { return promise.then([](T) { } ); } void reraise_kj_exception(); void check_py_error(); kj::Promise wrapPyFunc(PyObject * func, PyObject * arg); kj::Promise wrapPyFuncNoArg(PyObject * func); kj::Promise wrapRemoteCall(PyObject * func, capnp::Response & arg); ::kj::Promise then(kj::Promise & promise, PyObject * func, PyObject * error_func); ::kj::Promise then(::capnp::RemotePromise< ::capnp::DynamicStruct> & promise, PyObject * func, PyObject * error_func); ::kj::Promise then(kj::Promise & promise, PyObject * func, PyObject * error_func); ::kj::Promise then(kj::Promise > && promise); class PythonInterfaceDynamicImpl final: public capnp::DynamicCapability::Server { public: PyObject * py_server; PythonInterfaceDynamicImpl(capnp::InterfaceSchema & schema, PyObject * _py_server) : capnp::DynamicCapability::Server(schema), py_server(_py_server) { GILAcquire gil; Py_INCREF(_py_server); } ~PythonInterfaceDynamicImpl() { GILAcquire gil; Py_DECREF(py_server); } kj::Promise call(capnp::InterfaceSchema::Method method, capnp::CallContext< capnp::DynamicStruct, capnp::DynamicStruct> context); }; class PyRefCounter { public: PyObject * obj; PyRefCounter(PyObject * o) : obj(o) { GILAcquire gil; Py_INCREF(obj); } PyRefCounter(const PyRefCounter & ref) : obj(ref.obj) { GILAcquire gil; Py_INCREF(obj); } ~PyRefCounter() { GILAcquire gil; Py_DECREF(obj); } }; inline capnp::DynamicCapability::Client new_client(capnp::InterfaceSchema & schema, PyObject * server) { return capnp::DynamicCapability::Client(kj::heap(schema, server)); } inline capnp::DynamicValue::Reader new_server(capnp::InterfaceSchema & schema, PyObject * server) { return capnp::DynamicValue::Reader(kj::heap(schema, server)); } inline capnp::Capability::Client server_to_client(capnp::InterfaceSchema & schema, PyObject * server) { return kj::heap(schema, server); } void init_capnp_api();