// // Copyright (c) ZeroC, Inc. All rights reserved. // #include #include #include #include using namespace std; using namespace IcePy; namespace IcePy { struct DispatcherCallObject { PyObject_HEAD Ice::DispatcherCallPtr* call; }; } #ifdef WIN32 extern "C" #endif static void dispatcherCallDealloc(DispatcherCallObject* self) { delete self->call; Py_TYPE(self)->tp_free(reinterpret_cast(self)); } #ifdef WIN32 extern "C" #endif static PyObject* dispatcherCallInvoke(DispatcherCallObject* self, PyObject* /*args*/, PyObject* /*kwds*/) { try { AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. (*self->call)->run(); } catch(const Ice::Exception& ex) { setPythonException(ex); return 0; } return incRef(Py_None); } namespace IcePy { PyTypeObject DispatcherCallType = { /* The ob_type field must be initialized in the module init function * to be portable to Windows without using C++. */ PyVarObject_HEAD_INIT(0, 0) STRCAST("IcePy.DispatcherCall"), /* tp_name */ sizeof(DispatcherCallObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ reinterpret_cast(dispatcherCallDealloc), /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ reinterpret_cast(dispatcherCallInvoke), /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ }; } bool IcePy::initDispatcher(PyObject* module) { if(PyType_Ready(&DispatcherCallType) < 0) { return false; } PyTypeObject* type = &DispatcherCallType; // Necessary to prevent GCC's strict-alias warnings. if(PyModule_AddObject(module, STRCAST("DispatcherCall"), reinterpret_cast(type)) < 0) { return false; } return true; } IcePy::Dispatcher::Dispatcher(PyObject* dispatcher) : _dispatcher(dispatcher) { if(!PyCallable_Check(dispatcher)) { throw Ice::InitializationException(__FILE__, __LINE__, "dispatcher must be a callable"); } Py_INCREF(dispatcher); } void IcePy::Dispatcher::setCommunicator(const Ice::CommunicatorPtr& communicator) { _communicator = communicator; } void IcePy::Dispatcher::dispatch(const Ice::DispatcherCallPtr& call, const Ice::ConnectionPtr& con) { AdoptThread adoptThread; // Ensure the current thread is able to call into Python. DispatcherCallObject* obj = reinterpret_cast(DispatcherCallType.tp_alloc(&DispatcherCallType, 0)); if(!obj) { return; } obj->call = new Ice::DispatcherCallPtr(call); PyObjectHandle c = createConnection(con, _communicator); PyObjectHandle tmp = PyObject_CallFunction(_dispatcher.get(), STRCAST("OO"), obj, c.get()); Py_DECREF(reinterpret_cast(obj)); if(!tmp.get()) { throwPythonException(); } }