diff options
Diffstat (limited to 'python/modules')
-rw-r--r-- | python/modules/IcePy/Communicator.cpp | 144 | ||||
-rw-r--r-- | python/modules/IcePy/Connection.cpp | 4 | ||||
-rw-r--r-- | python/modules/IcePy/ConnectionInfo.cpp | 8 | ||||
-rw-r--r-- | python/modules/IcePy/Endpoint.cpp | 4 | ||||
-rw-r--r-- | python/modules/IcePy/EndpointInfo.cpp | 4 | ||||
-rw-r--r-- | python/modules/IcePy/ImplicitContext.cpp | 4 | ||||
-rw-r--r-- | python/modules/IcePy/Init.cpp | 5 | ||||
-rw-r--r-- | python/modules/IcePy/Makefile | 4 | ||||
-rw-r--r-- | python/modules/IcePy/Makefile.mak | 4 | ||||
-rw-r--r-- | python/modules/IcePy/ObjectAdapter.cpp | 4 | ||||
-rw-r--r-- | python/modules/IcePy/ObjectFactory.cpp | 221 | ||||
-rw-r--r-- | python/modules/IcePy/ObjectFactory.h | 53 | ||||
-rw-r--r-- | python/modules/IcePy/Operation.cpp | 136 | ||||
-rw-r--r-- | python/modules/IcePy/Proxy.cpp | 4 | ||||
-rw-r--r-- | python/modules/IcePy/Types.cpp | 234 | ||||
-rw-r--r-- | python/modules/IcePy/Types.h | 195 | ||||
-rw-r--r-- | python/modules/IcePy/Util.h | 2 | ||||
-rw-r--r-- | python/modules/IcePy/ValueFactoryManager.cpp | 536 | ||||
-rw-r--r-- | python/modules/IcePy/ValueFactoryManager.h | 95 |
19 files changed, 1015 insertions, 646 deletions
diff --git a/python/modules/IcePy/Communicator.cpp b/python/modules/IcePy/Communicator.cpp index 1492c24c1ee..3f2d56e4c32 100644 --- a/python/modules/IcePy/Communicator.cpp +++ b/python/modules/IcePy/Communicator.cpp @@ -16,7 +16,6 @@ #include <ImplicitContext.h> #include <Logger.h> #include <ObjectAdapter.h> -#include <ObjectFactory.h> #include <Operation.h> #include <Properties.h> #include <PropertiesAdmin.h> @@ -24,6 +23,7 @@ #include <Thread.h> #include <Types.h> #include <Util.h> +#include <ValueFactoryManager.h> #include <Ice/ValueFactory.h> #include <Ice/Initialize.h> #include <Ice/CommunicatorAsync.h> @@ -142,12 +142,14 @@ communicatorInit(CommunicatorObject* self, PyObject* args, PyObject* /*kwds*/) bool hasArgs = argList != 0; Ice::InitializationData data; + if(initData) { PyObjectHandle properties = PyObject_GetAttrString(initData, STRCAST("properties")); PyObjectHandle logger = PyObject_GetAttrString(initData, STRCAST("logger")); PyObjectHandle threadHook = PyObject_GetAttrString(initData, STRCAST("threadHook")); PyObjectHandle batchRequestInterceptor = PyObject_GetAttrString(initData, STRCAST("batchRequestInterceptor")); + PyErr_Clear(); // PyObject_GetAttrString sets an error on failure. if(properties.get() && properties.get() != Py_None) @@ -176,6 +178,11 @@ communicatorInit(CommunicatorObject* self, PyObject* args, PyObject* /*kwds*/) } } + // + // We always supply our own implementation of ValueFactoryManager. + // + data.valueFactoryManager = new ValueFactoryManager; + try { if(argList) @@ -254,8 +261,6 @@ communicatorInit(CommunicatorObject* self, PyObject* args, PyObject* /*kwds*/) delete[] argv; self->communicator = new Ice::CommunicatorPtr(communicator); - ObjectFactoryPtr factory = new ObjectFactory; - (*self->communicator)->addObjectFactory(factory, ""); CommunicatorMap::iterator p = _communicatorMap.find(communicator); if(p != _communicatorMap.end()) @@ -302,6 +307,10 @@ static PyObject* communicatorDestroy(CommunicatorObject* self) { assert(self->communicator); + + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast((*self->communicator)->getValueFactoryManager()); + assert(vfm); + try { AllowThreads allowThreads; // Release Python's global interpreter lock to avoid a potential deadlock. @@ -310,17 +319,25 @@ communicatorDestroy(CommunicatorObject* self) catch(const Ice::Exception& ex) { setPythonException(ex); - return 0; } + vfm->destroy(); + // // Break cyclic reference between this object and its Python wrapper. // Py_XDECREF(self->wrapper); self->wrapper = 0; - Py_INCREF(Py_None); - return Py_None; + if(PyErr_Occurred()) + { + return 0; + } + else + { + Py_INCREF(Py_None); + return Py_None; + } } #ifdef WIN32 @@ -1169,12 +1186,16 @@ extern "C" static PyObject* communicatorAddObjectFactory(CommunicatorObject* self, PyObject* args) { - PyObject* factoryType = lookupType("Ice.ObjectFactory"); - assert(factoryType); + PyObject* objectFactoryType = lookupType("Ice.ObjectFactory"); + assert(objectFactoryType); + PyObject* valueFactoryType = lookupType("types.FunctionType"); + assert(valueFactoryType); - PyObject* factory; + PyObject* objectFactory; PyObject* strObj; - if(!PyArg_ParseTuple(args, STRCAST("O!O"), factoryType, &factory, &strObj)) + PyObject* valueFactory; + if(!PyArg_ParseTuple(args, STRCAST("O!OO!"), objectFactoryType, &objectFactory, &strObj, valueFactoryType, + &valueFactory)) { return 0; } @@ -1185,55 +1206,12 @@ communicatorAddObjectFactory(CommunicatorObject* self, PyObject* args) return 0; } - ObjectFactoryPtr pof; - try - { - pof = ObjectFactoryPtr::dynamicCast((*self->communicator)->findObjectFactory("")); - assert(pof); - } - catch(const Ice::Exception& ex) - { - setPythonException(ex); - return 0; - - } - - if(!pof->addObjectFactory(factory, id)) - { - return 0; - } - - Py_INCREF(Py_None); - return Py_None; -} - -#ifdef WIN32 -extern "C" -#endif -static PyObject* -communicatorAddValueFactory(CommunicatorObject* self, PyObject* args) -{ - PyObject* factoryType = lookupType("types.FunctionType"); - assert(factoryType); - - PyObject* factory; - PyObject* strObj; - if(!PyArg_ParseTuple(args, STRCAST("O!O"), factoryType, &factory, &strObj)) - { - return 0; - } - - string id; - if(!getStringArg(strObj, "id", id)) - { - return 0; - } + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast((*self->communicator)->getValueFactoryManager()); + assert(vfm); - ObjectFactoryPtr pof; try { - pof = ObjectFactoryPtr::dynamicCast((*self->communicator)->findObjectFactory("")); - assert(pof); + vfm->add(valueFactory, objectFactory, id); } catch(const Ice::Exception& ex) { @@ -1242,11 +1220,6 @@ communicatorAddValueFactory(CommunicatorObject* self, PyObject* args) } - if(!pof->addValueFactory(factory, id)) - { - return 0; - } - Py_INCREF(Py_None); return Py_None; } @@ -1269,52 +1242,21 @@ communicatorFindObjectFactory(CommunicatorObject* self, PyObject* args) return 0; } - ObjectFactoryPtr pof; - try - { - pof = ObjectFactoryPtr::dynamicCast((*self->communicator)->findObjectFactory("")); - assert(pof); - } - catch(const Ice::Exception& ex) - { - setPythonException(ex); - return 0; - } + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast((*self->communicator)->getValueFactoryManager()); + assert(vfm); - return pof->findObjectFactory(id); + return vfm->findObjectFactory(id); } #ifdef WIN32 extern "C" #endif static PyObject* -communicatorFindValueFactory(CommunicatorObject* self, PyObject* args) +communicatorGetValueFactoryManager(CommunicatorObject* self) { - PyObject* strObj; - if(!PyArg_ParseTuple(args, STRCAST("O"), &strObj)) - { - return 0; - } - - string id; - if(!getStringArg(strObj, "id", id)) - { - return 0; - } - - ObjectFactoryPtr pof; - try - { - pof = ObjectFactoryPtr::dynamicCast((*self->communicator)->findObjectFactory("")); - assert(pof); - } - catch(const Ice::Exception& ex) - { - setPythonException(ex); - return 0; - } + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast((*self->communicator)->getValueFactoryManager()); - return pof->findValueFactory(id); + return vfm->getObject(); } #ifdef WIN32 @@ -1648,10 +1590,8 @@ static PyMethodDef CommunicatorMethods[] = PyDoc_STR(STRCAST("addObjectFactory(factory, id) -> None")) }, { STRCAST("findObjectFactory"), reinterpret_cast<PyCFunction>(communicatorFindObjectFactory), METH_VARARGS, PyDoc_STR(STRCAST("findObjectFactory(id) -> Ice.ObjectFactory")) }, - { STRCAST("addValueFactory"), reinterpret_cast<PyCFunction>(communicatorAddValueFactory), METH_VARARGS, - PyDoc_STR(STRCAST("addValueFactory(factory, id) -> None")) }, - { STRCAST("findValueFactory"), reinterpret_cast<PyCFunction>(communicatorFindValueFactory), METH_VARARGS, - PyDoc_STR(STRCAST("findValueFactory(id) -> Ice.ValueFactory")) }, + { STRCAST("getValueFactoryManager"), reinterpret_cast<PyCFunction>(communicatorGetValueFactoryManager), METH_NOARGS, + PyDoc_STR(STRCAST("getValueFactoryManager() -> Ice.ValueFactoryManager")) }, { STRCAST("getImplicitContext"), reinterpret_cast<PyCFunction>(communicatorGetImplicitContext), METH_NOARGS, PyDoc_STR(STRCAST("getImplicitContext() -> Ice.ImplicitContext")) }, { STRCAST("getProperties"), reinterpret_cast<PyCFunction>(communicatorGetProperties), METH_NOARGS, diff --git a/python/modules/IcePy/Connection.cpp b/python/modules/IcePy/Connection.cpp index 2aa28f893df..28f3c69681b 100644 --- a/python/modules/IcePy/Connection.cpp +++ b/python/modules/IcePy/Connection.cpp @@ -232,9 +232,7 @@ connectionCompare(ConnectionObject* c1, PyObject* other, int op) } } - PyObject* r = result ? getTrue() : getFalse(); - Py_INCREF(r); - return r; + return result ? incTrue() : incFalse(); } #ifdef WIN32 diff --git a/python/modules/IcePy/ConnectionInfo.cpp b/python/modules/IcePy/ConnectionInfo.cpp index 2b7750c1cf8..7538c0503f4 100644 --- a/python/modules/IcePy/ConnectionInfo.cpp +++ b/python/modules/IcePy/ConnectionInfo.cpp @@ -56,9 +56,7 @@ extern "C" static PyObject* connectionInfoGetIncoming(ConnectionInfoObject* self) { - PyObject* result = (*self->connectionInfo)->incoming ? getTrue() : getFalse(); - Py_INCREF(result); - return result; + return (*self->connectionInfo)->incoming ? incTrue() : incFalse(); } #ifdef WIN32 @@ -212,9 +210,7 @@ sslConnectionInfoGetVerified(ConnectionInfoObject* self) { IceSSL::ConnectionInfoPtr info = IceSSL::ConnectionInfoPtr::dynamicCast(*self->connectionInfo); assert(info); - PyObject* result = info->incoming ? getTrue() : getFalse(); - Py_INCREF(result); - return result; + return info->incoming ? incTrue() : incFalse(); } #ifdef WIN32 diff --git a/python/modules/IcePy/Endpoint.cpp b/python/modules/IcePy/Endpoint.cpp index 0ee59b6c757..907aa7b12e1 100644 --- a/python/modules/IcePy/Endpoint.cpp +++ b/python/modules/IcePy/Endpoint.cpp @@ -99,9 +99,7 @@ endpointCompare(EndpointObject* p1, PyObject* other, int op) } } - PyObject* r = result ? getTrue() : getFalse(); - Py_INCREF(r); - return r; + return result ? incTrue() : incFalse(); } #ifdef WIN32 diff --git a/python/modules/IcePy/EndpointInfo.cpp b/python/modules/IcePy/EndpointInfo.cpp index 50065c75c13..22579a05160 100644 --- a/python/modules/IcePy/EndpointInfo.cpp +++ b/python/modules/IcePy/EndpointInfo.cpp @@ -135,9 +135,7 @@ extern "C" static PyObject* endpointInfoGetCompress(EndpointInfoObject* self) { - PyObject* result = (*self->endpointInfo)->compress ? getTrue() : getFalse(); - Py_INCREF(result); - return result; + return (*self->endpointInfo)->compress ? incTrue() : incFalse(); } #ifdef WIN32 diff --git a/python/modules/IcePy/ImplicitContext.cpp b/python/modules/IcePy/ImplicitContext.cpp index b1a183b0d47..320e9a422d7 100644 --- a/python/modules/IcePy/ImplicitContext.cpp +++ b/python/modules/IcePy/ImplicitContext.cpp @@ -108,9 +108,7 @@ implicitContextCompare(ImplicitContextObject* c1, PyObject* other, int op) } } - PyObject* r = result ? getTrue() : getFalse(); - Py_INCREF(r); - return r; + return result ? incTrue() : incFalse(); } #ifdef WIN32 diff --git a/python/modules/IcePy/Init.cpp b/python/modules/IcePy/Init.cpp index 0a594104b61..337298eed97 100644 --- a/python/modules/IcePy/Init.cpp +++ b/python/modules/IcePy/Init.cpp @@ -26,6 +26,7 @@ #include <Proxy.h> #include <Slice.h> #include <Types.h> +#include <ValueFactoryManager.h> #include <Ice/Initialize.h> using namespace std; @@ -230,6 +231,10 @@ initIcePy(void) { INIT_RETURN; } + if(!initValueFactoryManager(module)) + { + INIT_RETURN; + } #if PY_VERSION_HEX >= 0x03000000 return module; diff --git a/python/modules/IcePy/Makefile b/python/modules/IcePy/Makefile index 72e252b757f..64f1038dd56 100644 --- a/python/modules/IcePy/Makefile +++ b/python/modules/IcePy/Makefile @@ -26,7 +26,6 @@ OBJS = BatchRequestInterceptor.o \ Init.o \ Logger.o \ ObjectAdapter.o \ - ObjectFactory.o \ Operation.o \ Properties.o \ PropertiesAdmin.o \ @@ -34,7 +33,8 @@ OBJS = BatchRequestInterceptor.o \ Slice.o \ Thread.o \ Types.o \ - Util.o + Util.o \ + ValueFactoryManager.o include $(top_srcdir)/config/Make.rules diff --git a/python/modules/IcePy/Makefile.mak b/python/modules/IcePy/Makefile.mak index 4473a818f67..21085772afa 100644 --- a/python/modules/IcePy/Makefile.mak +++ b/python/modules/IcePy/Makefile.mak @@ -25,7 +25,6 @@ OBJS = .\BatchRequestInterceptor.obj \ .\Init.obj \ .\Logger.obj \ .\ObjectAdapter.obj \ - .\ObjectFactory.obj \ .\Operation.obj \ .\Properties.obj \ .\PropertiesAdmin.obj \ @@ -33,7 +32,8 @@ OBJS = .\BatchRequestInterceptor.obj \ .\Slice.obj \ .\Thread.obj \ .\Types.obj \ - .\Util.obj + .\Util.obj \ + .\ValueFactoryManager.obj # diff --git a/python/modules/IcePy/ObjectAdapter.cpp b/python/modules/IcePy/ObjectAdapter.cpp index f57c58884d1..c81ca4c7143 100644 --- a/python/modules/IcePy/ObjectAdapter.cpp +++ b/python/modules/IcePy/ObjectAdapter.cpp @@ -164,7 +164,7 @@ IcePy::ServantLocatorWrapper::locate(const Ice::Current& current, Ice::LocalObje PyObject* userExceptionType = lookupType("Ice.UserException"); if(PyObject_IsInstance(ex.ex.get(), userExceptionType)) { - throw ExceptionWriter(current.adapter->getCommunicator(), ex.ex); + throw ExceptionWriter(ex.ex); } ex.raise(); @@ -243,7 +243,7 @@ IcePy::ServantLocatorWrapper::finished(const Ice::Current& current, const Ice::O PyObject* userExceptionType = lookupType("Ice.UserException"); if(PyObject_IsInstance(ex.ex.get(), userExceptionType)) { - throw ExceptionWriter(current.adapter->getCommunicator(), ex.ex); + throw ExceptionWriter(ex.ex); } ex.raise(); diff --git a/python/modules/IcePy/ObjectFactory.cpp b/python/modules/IcePy/ObjectFactory.cpp deleted file mode 100644 index 376b5c83697..00000000000 --- a/python/modules/IcePy/ObjectFactory.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// ********************************************************************** -// -// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved. -// -// This copy of Ice is licensed to you under the terms described in the -// ICE_LICENSE file included in this distribution. -// -// ********************************************************************** - -#ifdef _WIN32 -# include <IceUtil/Config.h> -#endif -#include <ObjectFactory.h> -#include <Thread.h> -#include <Types.h> -#include <Util.h> -#include <Ice/LocalException.h> - -using namespace std; -using namespace IcePy; - -IcePy::ObjectFactory::ObjectFactory() -{ -} - -IcePy::ObjectFactory::~ObjectFactory() -{ - assert(_valueFactoryMap.empty()); - assert(_objectFactoryMap.empty()); -} - -Ice::ObjectPtr -IcePy::ObjectFactory::create(const string& id) -{ - PyObject* factory = 0; - - // - // Check if the application has registered a factory for this id. - // - { - Lock sync(*this); - - FactoryMap::iterator p = _valueFactoryMap.find(id); - if(p != _valueFactoryMap.end()) - { - factory = p->second; - } - } - - // - // Get the type information. - // - ClassInfoPtr info; - if(id == Ice::Object::ice_staticId()) - { - // - // When the ID is that of Ice::Object, it indicates that the stream has not - // found a factory and is providing us an opportunity to preserve the object. - // - info = lookupClassInfo("::Ice::UnknownSlicedObject"); - } - else - { - info = lookupClassInfo(id); - } - - if(!info) - { - return 0; - } - - if(factory) - { - // - // Invoke the create method on the Python factory object. - // - PyObjectHandle obj = PyObject_CallFunction(factory, STRCAST("s"), id.c_str()); - if(!obj.get()) - { - assert(PyErr_Occurred()); - throw AbortMarshaling(); - } - if(obj.get() == Py_None) - { - return 0; - } - return new ObjectReader(obj.get(), info); - } - - // - // If the requested type is an abstract class, then we give up. - // - if(info->isAbstract) - { - return 0; - } - - // - // Instantiate the object. - // - PyTypeObject* type = reinterpret_cast<PyTypeObject*>(info->pythonType.get()); - PyObjectHandle args = PyTuple_New(0); - PyObjectHandle obj = type->tp_new(type, args.get(), 0); - if(!obj.get()) - { - assert(PyErr_Occurred()); - throw AbortMarshaling(); - } - - return new ObjectReader(obj.get(), info); -} - -void -IcePy::ObjectFactory::destroy() -{ - FactoryMap valueFactories; - FactoryMap objectFactories; - - { - Lock sync(*this); - objectFactories = _objectFactoryMap; - valueFactories = _valueFactoryMap; - _valueFactoryMap.clear(); - _objectFactoryMap.clear(); - } - - // - // We release the GIL before calling communicator->destroy(), so we must - // reacquire it before calling back into Python. - // - AdoptThread adoptThread; - - for(FactoryMap::iterator p = _objectFactoryMap.begin(); p != _objectFactoryMap.end(); ++p) - { - // - // Invoke the destroy method on each registered Python "object" factory. - // - PyObjectHandle obj = PyObject_CallMethod(p->second, STRCAST("destroy"), 0); - PyErr_Clear(); // Ignore errors. - Py_DECREF(p->second); - } - for(FactoryMap::iterator p = _valueFactoryMap.begin(); p != _valueFactoryMap.end(); ++p) - { - PyErr_Clear(); // Ignore errors. - Py_DECREF(p->second); - } -} - -bool -IcePy::ObjectFactory::addValueFactory(PyObject* factory, const string& id) -{ - Lock sync(*this); - - FactoryMap::iterator p = _valueFactoryMap.find(id); - if(p != _valueFactoryMap.end()) - { - Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); - ex.kindOfObject = "value factory"; - ex.id = id; - setPythonException(ex); - return false; - } - - _valueFactoryMap.insert(FactoryMap::value_type(id, factory)); - Py_INCREF(factory); - - return true; -} - -bool -IcePy::ObjectFactory::addObjectFactory(PyObject* factory, const string& id) -{ - Lock sync(*this); - - FactoryMap::iterator p = _valueFactoryMap.find(id); - if(p != _valueFactoryMap.end()) - { - Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); - ex.kindOfObject = "value factory"; - ex.id = id; - setPythonException(ex); - return false; - } - - _objectFactoryMap.insert(FactoryMap::value_type(id, factory)); - Py_INCREF(factory); - - return true; -} - -PyObject* -IcePy::ObjectFactory::findValueFactory(const string& id) -{ - Lock sync(*this); - - FactoryMap::iterator p = _valueFactoryMap.find(id); - if(p == _valueFactoryMap.end()) - { - Py_INCREF(Py_None); - return Py_None; - } - - Py_INCREF(p->second); - return p->second; -} - -PyObject* -IcePy::ObjectFactory::findObjectFactory(const string& id) -{ - Lock sync(*this); - - FactoryMap::iterator p = _objectFactoryMap.find(id); - if(p == _objectFactoryMap.end()) - { - Py_INCREF(Py_None); - return Py_None; - } - - Py_INCREF(p->second); - return p->second; -} diff --git a/python/modules/IcePy/ObjectFactory.h b/python/modules/IcePy/ObjectFactory.h deleted file mode 100644 index 57b93352bdd..00000000000 --- a/python/modules/IcePy/ObjectFactory.h +++ /dev/null @@ -1,53 +0,0 @@ -// ********************************************************************** -// -// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved. -// -// This copy of Ice is licensed to you under the terms described in the -// ICE_LICENSE file included in this distribution. -// -// ********************************************************************** - -#ifndef ICEPY_OBJECT_FACTORY_H -#define ICEPY_OBJECT_FACTORY_H - -#include <Config.h> -#include <Ice/ObjectF.h> -#include <Ice/ObjectFactory.h> -#include <IceUtil/Mutex.h> - -namespace IcePy -{ - -// -// Each communicator registers an instance of ObjectFactory as its -// default object factory. This instance delegates to registered Python -// objects, and instantiates concrete classes when no factory is present. -// -class ObjectFactory : public Ice::ObjectFactory, public IceUtil::Mutex -{ -public: - - ObjectFactory(); - ~ObjectFactory(); - - virtual Ice::ObjectPtr create(const std::string&); - - virtual void destroy(); - - bool addValueFactory(PyObject*, const std::string&); - bool addObjectFactory(PyObject*, const std::string&); - - PyObject* findValueFactory(const std::string&); - PyObject* findObjectFactory(const std::string&); - -private: - - typedef std::map<std::string, PyObject*> FactoryMap; - FactoryMap _valueFactoryMap; - FactoryMap _objectFactoryMap; -}; -typedef IceUtil::Handle<ObjectFactory> ObjectFactoryPtr; - -} - -#endif diff --git a/python/modules/IcePy/Operation.cpp b/python/modules/IcePy/Operation.cpp index 42cb836fa9b..696f3291214 100644 --- a/python/modules/IcePy/Operation.cpp +++ b/python/modules/IcePy/Operation.cpp @@ -125,7 +125,7 @@ protected: enum MappingType { SyncMapping, AsyncMapping, OldAsyncMapping }; - bool prepareRequest(PyObject*, MappingType, Ice::OutputStreamPtr&, pair<const Ice::Byte*, const Ice::Byte*>&); + bool prepareRequest(PyObject*, MappingType, Ice::OutputStream*, pair<const Ice::Byte*, const Ice::Byte*>&); PyObject* unmarshalResults(const pair<const Ice::Byte*, const Ice::Byte*>&); PyObject* unmarshalException(const pair<const Ice::Byte*, const Ice::Byte*>&); bool validateException(PyObject*) const; @@ -378,27 +378,18 @@ struct AsyncResultObject extern PyTypeObject OperationType; extern PyTypeObject AMDCallbackType; -class UserExceptionReaderFactoryI : public Ice::UserExceptionReaderFactory +class UserExceptionFactory : public Ice::UserExceptionFactory { public: - UserExceptionReaderFactoryI(const Ice::CommunicatorPtr& communicator) : - _communicator(communicator) - { - } - - virtual void createAndThrow(const string& id) const + virtual void createAndThrow(const string& id) { ExceptionInfoPtr info = lookupExceptionInfo(id); if(info) { - throw ExceptionReader(_communicator, info); + throw ExceptionReader(info); } } - -private: - - const Ice::CommunicatorPtr _communicator; }; } @@ -1498,7 +1489,7 @@ IcePy::TypedInvocation::TypedInvocation(const Ice::ObjectPrx& prx, const Operati } bool -IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice::OutputStreamPtr& os, +IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice::OutputStream* os, pair<const Ice::Byte*, const Ice::Byte*>& params) { assert(PyTuple_Check(args)); @@ -1536,7 +1527,6 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice: // // Marshal the in parameters. // - os = Ice::createOutputStream(_communicator); os->startEncapsulation(_prx->ice_getEncodingVersion(), _op->format); ObjectMap objectMap; @@ -1591,7 +1581,7 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice: { ParamInfoPtr info = *p; PyObject* arg = PyTuple_GET_ITEM(args, info->pos); - if(arg != Unset && os->writeOptional(info->tag, info->type->optionalFormat())) + if(arg != Unset && os->writeOpt(info->tag, info->type->optionalFormat())) { info->type->marshal(arg, os, &objectMap, true, &info->metaData); } @@ -1632,17 +1622,17 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: PyObjectHandle results = PyTuple_New(numResults); if(results.get() && numResults > 0) { - Ice::InputStreamPtr is = Ice::wrapInputStream(_communicator, bytes); + Ice::InputStream is(_communicator, bytes); // - // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // Store a pointer to a local StreamUtil object as the stream's closure. // This is necessary to support object unmarshaling (see ObjectReader). // - SlicedDataUtil util; - assert(!is->closure()); - is->closure(&util); + StreamUtil util; + assert(!is.getClosure()); + is.setClosure(&util); - is->startEncapsulation(); + is.startEncapsulation(); ParamInfoList::iterator p; @@ -1655,7 +1645,7 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: if(!info->optional) { void* closure = reinterpret_cast<void*>(info->pos); - info->type->unmarshal(is, info, results.get(), closure, false, &info->metaData); + info->type->unmarshal(&is, info, results.get(), closure, false, &info->metaData); } } @@ -1666,7 +1656,7 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: { assert(_op->returnType->pos == 0); void* closure = reinterpret_cast<void*>(_op->returnType->pos); - _op->returnType->type->unmarshal(is, _op->returnType, results.get(), closure, false, &_op->metaData); + _op->returnType->type->unmarshal(&is, _op->returnType, results.get(), closure, false, &_op->metaData); } // @@ -1675,10 +1665,10 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: for(p = _op->optionalOutParams.begin(); p != _op->optionalOutParams.end(); ++p) { ParamInfoPtr info = *p; - if(is->readOptional(info->tag, info->type->optionalFormat())) + if(is.readOpt(info->tag, info->type->optionalFormat())) { void* closure = reinterpret_cast<void*>(info->pos); - info->type->unmarshal(is, info, results.get(), closure, true, &info->metaData); + info->type->unmarshal(&is, info, results.get(), closure, true, &info->metaData); } else { @@ -1692,12 +1682,12 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: if(_op->returnsClasses) { - is->readPendingObjects(); + is.readPendingObjects(); } - is->endEncapsulation(); + is.endEncapsulation(); - util.update(); + util.updateSlicedData(); } return results.release(); @@ -1706,37 +1696,37 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: PyObject* IcePy::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const Ice::Byte*>& bytes) { - Ice::InputStreamPtr is = Ice::wrapInputStream(_communicator, bytes); + Ice::InputStream is(_communicator, bytes); // - // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // Store a pointer to a local StreamUtil object as the stream's closure. // This is necessary to support object unmarshaling (see ObjectReader). // - SlicedDataUtil util; - assert(!is->closure()); - is->closure(&util); + StreamUtil util; + assert(!is.getClosure()); + is.setClosure(&util); - is->startEncapsulation(); + is.startEncapsulation(); try { - Ice::UserExceptionReaderFactoryPtr factory = new UserExceptionReaderFactoryI(_communicator); - is->throwException(factory); + Ice::UserExceptionFactoryPtr factory = new UserExceptionFactory; + is.throwException(factory); } catch(const ExceptionReader& r) { - is->endEncapsulation(); + is.endEncapsulation(); PyObject* ex = r.getException(); if(validateException(ex)) { - util.update(); + util.updateSlicedData(); Ice::SlicedDataPtr slicedData = r.getSlicedData(); if(slicedData) { - SlicedDataUtil::setMember(ex, slicedData); + StreamUtil::setSlicedDataMember(ex, slicedData); } Py_INCREF(ex); @@ -1800,9 +1790,9 @@ IcePy::SyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) // // Marshal the input parameters to a byte sequence. // - Ice::OutputStreamPtr os; + Ice::OutputStream os(_communicator); pair<const Ice::Byte*, const Ice::Byte*> params; - if(!prepareRequest(pyparams, SyncMapping, os, params)) + if(!prepareRequest(pyparams, SyncMapping, &os, params)) { return 0; } @@ -2004,9 +1994,9 @@ IcePy::AsyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) // // Marshal the input parameters to a byte sequence. // - Ice::OutputStreamPtr os; + Ice::OutputStream os(_communicator); pair<const Ice::Byte*, const Ice::Byte*> params; - if(!prepareRequest(pyparams, AsyncMapping, os, params)) + if(!prepareRequest(pyparams, AsyncMapping, &os, params)) { return 0; } @@ -2289,9 +2279,9 @@ IcePy::OldAsyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) // // Marshal the input parameters to a byte sequence. // - Ice::OutputStreamPtr os; + Ice::OutputStream os(_communicator); pair<const Ice::Byte*, const Ice::Byte*> params; - if(!prepareRequest(pyparams, OldAsyncMapping, os, params)) + if(!prepareRequest(pyparams, OldAsyncMapping, &os, params)) { return 0; } @@ -3246,19 +3236,19 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con if(!_op->inParams.empty()) { - Ice::InputStreamPtr is = Ice::wrapInputStream(_communicator, inBytes); + Ice::InputStream is(_communicator, inBytes); // - // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // Store a pointer to a local StreamUtil object as the stream's closure. // This is necessary to support object unmarshaling (see ObjectReader). // - SlicedDataUtil util; - assert(!is->closure()); - is->closure(&util); + StreamUtil util; + assert(!is.getClosure()); + is.setClosure(&util); try { - is->startEncapsulation(); + is.startEncapsulation(); ParamInfoList::iterator p; @@ -3271,7 +3261,7 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con if(!info->optional) { void* closure = reinterpret_cast<void*>(info->pos + offset); - info->type->unmarshal(is, info, args.get(), closure, false, &info->metaData); + info->type->unmarshal(&is, info, args.get(), closure, false, &info->metaData); } } @@ -3281,10 +3271,10 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con for(p = _op->optionalInParams.begin(); p != _op->optionalInParams.end(); ++p) { ParamInfoPtr info = *p; - if(is->readOptional(info->tag, info->type->optionalFormat())) + if(is.readOpt(info->tag, info->type->optionalFormat())) { void* closure = reinterpret_cast<void*>(info->pos + offset); - info->type->unmarshal(is, info, args.get(), closure, true, &info->metaData); + info->type->unmarshal(&is, info, args.get(), closure, true, &info->metaData); } else { @@ -3298,12 +3288,12 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con if(_op->sendsClasses) { - is->readPendingObjects(); + is.readPendingObjects(); } - is->endEncapsulation(); + is.endEncapsulation(); - util.update(); + util.updateSlicedData(); } catch(const AbortMarshaling&) { @@ -3394,7 +3384,7 @@ IcePy::TypedUpcall::response(PyObject* args, const Ice::EncodingVersion& encodin // Marshal the results. If there is more than one value to be returned, then they must be // returned in a tuple of the form (result, outParam1, ...). // - Ice::OutputStreamPtr os = Ice::createOutputStream(_communicator); + Ice::OutputStream os(_communicator); try { Py_ssize_t numResults = static_cast<Py_ssize_t>(_op->outParams.size()); @@ -3433,7 +3423,7 @@ IcePy::TypedUpcall::response(PyObject* args, const Ice::EncodingVersion& encodin } Py_INCREF(args); - os->startEncapsulation(encoding, _op->format); + os.startEncapsulation(encoding, _op->format); ObjectMap objectMap; ParamInfoList::iterator p; @@ -3478,7 +3468,7 @@ IcePy::TypedUpcall::response(PyObject* args, const Ice::EncodingVersion& encodin if(!info->optional) { PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); - info->type->marshal(arg, os, &objectMap, false, &info->metaData); + info->type->marshal(arg, &os, &objectMap, false, &info->metaData); } } @@ -3488,7 +3478,7 @@ IcePy::TypedUpcall::response(PyObject* args, const Ice::EncodingVersion& encodin if(_op->returnType && !_op->returnType->optional) { PyObject* res = PyTuple_GET_ITEM(t.get(), 0); - _op->returnType->type->marshal(res, os, &objectMap, false, &_op->metaData); + _op->returnType->type->marshal(res, &os, &objectMap, false, &_op->metaData); } // @@ -3498,21 +3488,21 @@ IcePy::TypedUpcall::response(PyObject* args, const Ice::EncodingVersion& encodin { ParamInfoPtr info = *p; PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); - if(arg != Unset && os->writeOptional(info->tag, info->type->optionalFormat())) + if(arg != Unset && os.writeOpt(info->tag, info->type->optionalFormat())) { - info->type->marshal(arg, os, &objectMap, true, &info->metaData); + info->type->marshal(arg, &os, &objectMap, true, &info->metaData); } } if(_op->returnsClasses) { - os->writePendingObjects(); + os.writePendingObjects(); } - os->endEncapsulation(); + os.endEncapsulation(); AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. - _callback->ice_response(true, os->finished()); + _callback->ice_response(true, os.finished()); } catch(const AbortMarshaling&) { @@ -3569,16 +3559,16 @@ IcePy::TypedUpcall::exception(PyException& ex, const Ice::EncodingVersion& encod } else { - Ice::OutputStreamPtr os = Ice::createOutputStream(_communicator); - os->startEncapsulation(encoding, _op->format); + Ice::OutputStream os(_communicator); + os.startEncapsulation(encoding, _op->format); - ExceptionWriter writer(_communicator, ex.ex, info); - os->writeException(writer); + ExceptionWriter writer(ex.ex, info); + os.writeException(writer); - os->endEncapsulation(); + os.endEncapsulation(); AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. - _callback->ice_response(false, os->finished()); + _callback->ice_response(false, os.finished()); } } else diff --git a/python/modules/IcePy/Proxy.cpp b/python/modules/IcePy/Proxy.cpp index 293c3c16de8..adca91b26ab 100644 --- a/python/modules/IcePy/Proxy.cpp +++ b/python/modules/IcePy/Proxy.cpp @@ -145,9 +145,7 @@ proxyCompare(ProxyObject* p1, PyObject* other, int op) } } - PyObject* r = result ? getTrue() : getFalse(); - Py_INCREF(r); - return r; + return result ? incTrue() : incFalse(); } #ifdef WIN32 diff --git a/python/modules/IcePy/Types.cpp b/python/modules/IcePy/Types.cpp index f994ce46e80..b7aa87a8204 100644 --- a/python/modules/IcePy/Types.cpp +++ b/python/modules/IcePy/Types.cpp @@ -17,7 +17,9 @@ #include <Util.h> #include <IceUtil/InputUtil.h> #include <IceUtil/ScopedArray.h> +#include <Ice/InputStream.h> #include <Ice/LocalException.h> +#include <Ice/OutputStream.h> #include <Ice/SlicedData.h> #include <list> @@ -51,23 +53,6 @@ public: }; static InfoMapDestroyer infoMapDestroyer; -class ReadObjectCallback : public Ice::ReadObjectCallback -{ -public: - - ReadObjectCallback(const ClassInfoPtr&, const UnmarshalCallbackPtr&, PyObject*, void*); - ~ReadObjectCallback(); - - virtual void invoke(const ::Ice::ObjectPtr&); - -private: - - ClassInfoPtr _info; - UnmarshalCallbackPtr _cb; - PyObject* _target; - void* _closure; -}; - struct TypeInfoObject { PyObject_HEAD @@ -84,7 +69,7 @@ extern PyTypeObject TypeInfoType; extern PyTypeObject ExceptionInfoType; bool -writeString(PyObject* p, const Ice::OutputStreamPtr& os) +writeString(PyObject* p, Ice::OutputStream* os) { if(p == Py_None) { @@ -273,16 +258,16 @@ addExceptionInfo(const string& id, const ExceptionInfoPtr& info) } // -// SlicedDataUtil implementation +// StreamUtil implementation // -PyObject* IcePy::SlicedDataUtil::_slicedDataType = 0; -PyObject* IcePy::SlicedDataUtil::_sliceInfoType = 0; +PyObject* IcePy::StreamUtil::_slicedDataType = 0; +PyObject* IcePy::StreamUtil::_sliceInfoType = 0; -IcePy::SlicedDataUtil::SlicedDataUtil() +IcePy::StreamUtil::StreamUtil() { } -IcePy::SlicedDataUtil::~SlicedDataUtil() +IcePy::StreamUtil::~StreamUtil() { // // Make sure we break any cycles among the ObjectReaders in preserved slices. @@ -305,23 +290,29 @@ IcePy::SlicedDataUtil::~SlicedDataUtil() } void -IcePy::SlicedDataUtil::add(const ObjectReaderPtr& reader) +IcePy::StreamUtil::add(const ReadObjectCallbackPtr& callback) +{ + _callbacks.push_back(callback); +} + +void +IcePy::StreamUtil::add(const ObjectReaderPtr& reader) { assert(reader->getSlicedData()); _readers.insert(reader); } void -IcePy::SlicedDataUtil::update() +IcePy::StreamUtil::updateSlicedData() { for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p) { - setMember((*p)->getObject(), (*p)->getSlicedData()); + setSlicedDataMember((*p)->getObject(), (*p)->getSlicedData()); } } void -IcePy::SlicedDataUtil::setMember(PyObject* obj, const Ice::SlicedDataPtr& slicedData) +IcePy::StreamUtil::setSlicedDataMember(PyObject* obj, const Ice::SlicedDataPtr& slicedData) { // // Create a Python equivalent of the SlicedData object. @@ -487,7 +478,7 @@ IcePy::SlicedDataUtil::setMember(PyObject* obj, const Ice::SlicedDataPtr& sliced // named _ice_slicedData which is an instance of the Python class Ice.SlicedData. // Ice::SlicedDataPtr -IcePy::SlicedDataUtil::getMember(PyObject* obj, ObjectMap* objectMap) +IcePy::StreamUtil::getSlicedDataMember(PyObject* obj, ObjectMap* objectMap) { Ice::SlicedDataPtr slicedData; @@ -832,7 +823,7 @@ IcePy::PrimitiveInfo::optionalFormat() const } void -IcePy::PrimitiveInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*, bool, const Ice::StringSeq*) +IcePy::PrimitiveInfo::marshal(PyObject* p, Ice::OutputStream* os, ObjectMap*, bool, const Ice::StringSeq*) { switch(kind) { @@ -912,7 +903,7 @@ IcePy::PrimitiveInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, Objec } void -IcePy::PrimitiveInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, +IcePy::PrimitiveInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, PyObject* target, void* closure, bool, const Ice::StringSeq*) { switch(kind) @@ -1073,7 +1064,7 @@ IcePy::EnumInfo::optionalFormat() const } void -IcePy::EnumInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*, bool optional, const Ice::StringSeq*) +IcePy::EnumInfo::marshal(PyObject* p, Ice::OutputStream* os, ObjectMap*, bool optional, const Ice::StringSeq*) { // // Validate value. @@ -1089,7 +1080,7 @@ IcePy::EnumInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* } void -IcePy::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, +IcePy::EnumInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, PyObject* target, void* closure, bool, const Ice::StringSeq*) { Ice::Int val = is->readEnum(maxValue); @@ -1327,7 +1318,7 @@ IcePy::StructInfo::usesClasses() const } void -IcePy::StructInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional, +IcePy::StructInfo::marshal(PyObject* p, Ice::OutputStream* os, ObjectMap* objectMap, bool optional, const Ice::StringSeq*) { assert(p == Py_None || PyObject_IsInstance(p, pythonType.get()) == 1); // validate() should have caught this. @@ -1384,7 +1375,7 @@ IcePy::StructInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMa } void -IcePy::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, +IcePy::StructInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, PyObject* target, void* closure, bool optional, const Ice::StringSeq*) { PyObjectHandle p = instantiate(pythonType.get()); @@ -1528,7 +1519,7 @@ IcePy::SequenceInfo::usesClasses() const } void -IcePy::SequenceInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional, +IcePy::SequenceInfo::marshal(PyObject* p, Ice::OutputStream* os, ObjectMap* objectMap, bool optional, const Ice::StringSeq* metaData) { PrimitiveInfoPtr pi = PrimitiveInfoPtr::dynamicCast(elementType); @@ -1627,7 +1618,7 @@ IcePy::SequenceInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, Object } void -IcePy::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, +IcePy::SequenceInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, PyObject* target, void* closure, bool optional, const Ice::StringSeq* metaData) { if(optional) @@ -1772,7 +1763,7 @@ IcePy::SequenceInfo::getSequence(const PrimitiveInfoPtr& pi, PyObject* p) } void -IcePy::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, PyObject* p, const Ice::OutputStreamPtr& os) +IcePy::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, PyObject* p, Ice::OutputStream* os) { // // For most types, we accept an object that implements the buffer protocol @@ -2075,7 +2066,7 @@ IcePy::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, PyObje } void -IcePy::SequenceInfo::unmarshalPrimitiveSequence(const PrimitiveInfoPtr& pi, const Ice::InputStreamPtr& is, +IcePy::SequenceInfo::unmarshalPrimitiveSequence(const PrimitiveInfoPtr& pi, Ice::InputStream* is, const UnmarshalCallbackPtr& cb, PyObject* target, void* closure, const SequenceMappingPtr& sm) { @@ -2429,7 +2420,7 @@ IcePy::CustomInfo::usesClasses() const } void -IcePy::CustomInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool, +IcePy::CustomInfo::marshal(PyObject* p, Ice::OutputStream* os, ObjectMap* objectMap, bool, const Ice::StringSeq* metaData) { assert(PyObject_IsInstance(p, pythonType.get()) == 1); // validate() should have caught this. @@ -2464,7 +2455,7 @@ IcePy::CustomInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMa } void -IcePy::CustomInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, +IcePy::CustomInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, PyObject* target, void* closure, bool, const Ice::StringSeq* metaData) { // @@ -2601,7 +2592,7 @@ IcePy::DictionaryInfo::usesClasses() const } void -IcePy::DictionaryInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional, +IcePy::DictionaryInfo::marshal(PyObject* p, Ice::OutputStream* os, ObjectMap* objectMap, bool optional, const Ice::StringSeq*) { if(p != Py_None && !PyDict_Check(p)) @@ -2661,7 +2652,7 @@ IcePy::DictionaryInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, Obje } void -IcePy::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, +IcePy::DictionaryInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, PyObject* target, void* closure, bool optional, const Ice::StringSeq*) { if(optional) @@ -2871,7 +2862,7 @@ IcePy::ClassInfo::usesClasses() const } void -IcePy::ClassInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool, +IcePy::ClassInfo::marshal(PyObject* p, Ice::OutputStream* os, ObjectMap* objectMap, bool, const Ice::StringSeq*) { if(!pythonType.get()) @@ -2882,7 +2873,8 @@ IcePy::ClassInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap if(p == Py_None) { - os->writeObject(0); + Ice::ObjectPtr nil; + os->write(nil); return; } @@ -2914,11 +2906,24 @@ IcePy::ClassInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap // // Give the writer to the stream. The stream will eventually call write() on it. // - os->writeObject(writer); + os->write(writer); +} + +namespace +{ + +void +patchObject(void* addr, const Ice::ObjectPtr& v) +{ + ReadObjectCallback* cb = static_cast<ReadObjectCallback*>(addr); + assert(cb); + cb->invoke(v); +} + } void -IcePy::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, +IcePy::ClassInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, PyObject* target, void* closure, bool, const Ice::StringSeq*) { if(!pythonType.get()) @@ -2927,7 +2932,16 @@ IcePy::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallba throw AbortMarshaling(); } - is->readObject(new ReadObjectCallback(this, cb, target, closure)); + // + // This callback is notified when the Slice value is actually read. The StreamUtil object + // attached to the stream keeps a reference to the callback object to ensure it lives + // long enough. + // + ReadObjectCallbackPtr rocb = new ReadObjectCallback(this, cb, target, closure); + StreamUtil* util = reinterpret_cast<StreamUtil*>(is->getClosure()); + assert(util); + util->add(rocb); + is->read(patchObject, rocb.get()); } void @@ -3089,7 +3103,7 @@ IcePy::ProxyInfo::optionalFormat() const } void -IcePy::ProxyInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*, bool optional, const Ice::StringSeq*) +IcePy::ProxyInfo::marshal(PyObject* p, Ice::OutputStream* os, ObjectMap*, bool optional, const Ice::StringSeq*) { Ice::OutputStream::size_type sizePos = 0; if(optional) @@ -3117,7 +3131,7 @@ IcePy::ProxyInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap } void -IcePy::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, +IcePy::ProxyInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, PyObject* target, void* closure, bool optional, const Ice::StringSeq*) { if(optional) @@ -3140,7 +3154,7 @@ IcePy::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallba throw AbortMarshaling(); } - PyObjectHandle p = createProxy(proxy, is->communicator(), pythonType.get()); + PyObjectHandle p = createProxy(proxy, proxy->ice_getCommunicator(), pythonType.get()); cb->unmarshaled(p.get(), target, closure); } @@ -3213,7 +3227,7 @@ IcePy::ObjectWriter::ice_preMarshal() } void -IcePy::ObjectWriter::write(const Ice::OutputStreamPtr& os) const +IcePy::ObjectWriter::__write(Ice::OutputStream* os) const { Ice::SlicedDataPtr slicedData; @@ -3222,7 +3236,7 @@ IcePy::ObjectWriter::write(const Ice::OutputStreamPtr& os) const // // Retrieve the SlicedData object that we stored as a hidden member of the Python object. // - slicedData = SlicedDataUtil::getMember(_object, const_cast<ObjectMap*>(_map)); + slicedData = StreamUtil::getSlicedDataMember(_object, const_cast<ObjectMap*>(_map)); } os->startObject(slicedData); @@ -3247,7 +3261,13 @@ IcePy::ObjectWriter::write(const Ice::OutputStreamPtr& os) const } void -IcePy::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMemberList& members) const +IcePy::ObjectWriter::__read(Ice::InputStream*) +{ + assert(false); +} + +void +IcePy::ObjectWriter::writeMembers(Ice::OutputStream* os, const DataMemberList& members) const { for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { @@ -3271,7 +3291,7 @@ IcePy::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMemb } } else if(member->optional && - (val.get() == Unset || !os->writeOptional(member->tag, member->type->optionalFormat()))) + (val.get() == Unset || !os->writeOpt(member->tag, member->type->optionalFormat()))) { continue; } @@ -3316,7 +3336,13 @@ IcePy::ObjectReader::ice_postUnmarshal() } void -IcePy::ObjectReader::read(const Ice::InputStreamPtr& is) +IcePy::ObjectReader::__write(Ice::OutputStream*) const +{ + assert(false); +} + +void +IcePy::ObjectReader::__read(Ice::InputStream* is) { is->startObject(); @@ -3346,7 +3372,7 @@ IcePy::ObjectReader::read(const Ice::InputStreamPtr& is) for(p = info->optionalMembers.begin(); p != info->optionalMembers.end(); ++p) { DataMemberPtr member = *p; - if(is->readOptional(member->tag, member->type->optionalFormat())) + if(is->readOpt(member->tag, member->type->optionalFormat())) { member->type->unmarshal(is, member, _object, 0, true, &member->metaData); } @@ -3367,7 +3393,7 @@ IcePy::ObjectReader::read(const Ice::InputStreamPtr& is) if(_slicedData) { - SlicedDataUtil* util = reinterpret_cast<SlicedDataUtil*>(is->closure()); + StreamUtil* util = reinterpret_cast<StreamUtil*>(is->getClosure()); assert(util); util->add(this); @@ -3475,7 +3501,7 @@ IcePy::ReadObjectCallback::invoke(const Ice::ObjectPtr& p) // ExceptionInfo implementation. // void -IcePy::ExceptionInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap) +IcePy::ExceptionInfo::marshal(PyObject* p, Ice::OutputStream* os, ObjectMap* objectMap) { if(!PyObject_IsInstance(p, pythonType.get())) { @@ -3490,7 +3516,7 @@ IcePy::ExceptionInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, Objec // // Retrieve the SlicedData object that we stored as a hidden member of the Python object. // - slicedData = SlicedDataUtil::getMember(p, objectMap); + slicedData = StreamUtil::getSlicedDataMember(p, objectMap); } os->startException(slicedData); @@ -3512,7 +3538,7 @@ IcePy::ExceptionInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, Objec } void -IcePy::ExceptionInfo::writeMembers(PyObject* p, const Ice::OutputStreamPtr& os, const DataMemberList& members, +IcePy::ExceptionInfo::writeMembers(PyObject* p, Ice::OutputStream* os, const DataMemberList& members, ObjectMap* objectMap) const { for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) @@ -3537,7 +3563,7 @@ IcePy::ExceptionInfo::writeMembers(PyObject* p, const Ice::OutputStreamPtr& os, } } else if(member->optional && - (val.get() == Unset || !os->writeOptional(member->tag, member->type->optionalFormat()))) + (val.get() == Unset || !os->writeOpt(member->tag, member->type->optionalFormat()))) { continue; } @@ -3554,7 +3580,7 @@ IcePy::ExceptionInfo::writeMembers(PyObject* p, const Ice::OutputStreamPtr& os, } PyObject* -IcePy::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is) +IcePy::ExceptionInfo::unmarshal(Ice::InputStream* is) { PyObjectHandle p = createExceptionInstance(pythonType.get()); @@ -3577,7 +3603,7 @@ IcePy::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is) for(q = info->optionalMembers.begin(); q != info->optionalMembers.end(); ++q) { DataMemberPtr member = *q; - if(is->readOptional(member->tag, member->type->optionalFormat())) + if(is->readOpt(member->tag, member->type->optionalFormat())) { member->type->unmarshal(is, member, p.get(), 0, true, &member->metaData); } @@ -3664,9 +3690,8 @@ IcePy::ExceptionInfo::printMembers(PyObject* value, IceUtilInternal::Output& out // // ExceptionWriter implementation. // -IcePy::ExceptionWriter::ExceptionWriter(const Ice::CommunicatorPtr& communicator, const PyObjectHandle& ex, - const ExceptionInfoPtr& info) : - Ice::UserExceptionWriter(communicator), _ex(ex), _info(info) +IcePy::ExceptionWriter::ExceptionWriter(const PyObjectHandle& ex, const ExceptionInfoPtr& info) : + _ex(ex), _info(info) { if(!info) { @@ -3684,20 +3709,6 @@ IcePy::ExceptionWriter::~ExceptionWriter() throw() _ex = 0; } -void -IcePy::ExceptionWriter::write(const Ice::OutputStreamPtr& os) const -{ - AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - - _info->marshal(_ex.get(), os, const_cast<ObjectMap*>(&_objects)); -} - -bool -IcePy::ExceptionWriter::usesClasses() const -{ - return _info->usesClasses; -} - string IcePy::ExceptionWriter::ice_id() const { @@ -3724,39 +3735,40 @@ IcePy::ExceptionWriter::ice_throw() const throw *this; } -// -// ExceptionReader implementation. -// -IcePy::ExceptionReader::ExceptionReader(const Ice::CommunicatorPtr& communicator, const ExceptionInfoPtr& info) : - Ice::UserExceptionReader(communicator), _info(info) -{ -} - -IcePy::ExceptionReader::~ExceptionReader() throw() +void +IcePy::ExceptionWriter::__write(Ice::OutputStream* os) const { AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - _ex = 0; + _info->marshal(_ex.get(), os, const_cast<ObjectMap*>(&_objects)); } void -IcePy::ExceptionReader::read(const Ice::InputStreamPtr& is) const +IcePy::ExceptionWriter::__read(Ice::InputStream*) { - AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - - is->startException(); - - const_cast<PyObjectHandle&>(_ex) = _info->unmarshal(is); - - const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); } bool -IcePy::ExceptionReader::usesClasses() const +IcePy::ExceptionWriter::__usesClasses() const { return _info->usesClasses; } +// +// ExceptionReader implementation. +// +IcePy::ExceptionReader::ExceptionReader(const ExceptionInfoPtr& info) : + _info(info) +{ +} + +IcePy::ExceptionReader::~ExceptionReader() throw() +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + _ex = 0; +} + string IcePy::ExceptionReader::ice_id() const { @@ -3784,6 +3796,30 @@ IcePy::ExceptionReader::ice_throw() const throw *this; } +void +IcePy::ExceptionReader::__write(Ice::OutputStream*) const +{ + assert(false); +} + +void +IcePy::ExceptionReader::__read(Ice::InputStream* is) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + is->startException(); + + const_cast<PyObjectHandle&>(_ex) = _info->unmarshal(is); + + const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); +} + +bool +IcePy::ExceptionReader::__usesClasses() const +{ + return _info->usesClasses; +} + PyObject* IcePy::ExceptionReader::getException() const { diff --git a/python/modules/IcePy/Types.h b/python/modules/IcePy/Types.h index e2eee69e3a9..e67542f9195 100644 --- a/python/modules/IcePy/Types.h +++ b/python/modules/IcePy/Types.h @@ -12,7 +12,9 @@ #include <Config.h> #include <Util.h> -#include <Ice/Stream.h> +#include <Ice/FactoryTable.h> +#include <Ice/Object.h> +#include <Ice/SlicedDataF.h> #include <IceUtil/OutputUtil.h> #include <set> @@ -41,37 +43,6 @@ class ObjectReader; typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr; // -// This class keeps track of Python objects (instances of Slice classes -// and exceptions) that have preserved slices. -// -class SlicedDataUtil -{ -public: - - SlicedDataUtil(); - ~SlicedDataUtil(); - - void add(const ObjectReaderPtr&); - - void update(); - - static void setMember(PyObject*, const Ice::SlicedDataPtr&); - static Ice::SlicedDataPtr getMember(PyObject*, ObjectMap*); - -private: - - std::set<ObjectReaderPtr> _readers; - static PyObject* _slicedDataType; - static PyObject* _sliceInfoType; -}; - -struct PrintObjectHistory -{ - int index; - std::map<PyObject*, int> objects; -}; - -// // The delayed nature of class unmarshaling in the Ice protocol requires us to // handle unmarshaling using a callback strategy. An instance of UnmarshalCallback // is supplied to each type's unmarshal() member function. For all types except @@ -95,6 +66,71 @@ public: typedef IceUtil::Handle<UnmarshalCallback> UnmarshalCallbackPtr; // +// ReadObjectCallback retains all of the information necessary to store an unmarshaled +// Slice value as a Python object. +// +class ReadObjectCallback : public IceUtil::Shared +{ +public: + + ReadObjectCallback(const ClassInfoPtr&, const UnmarshalCallbackPtr&, PyObject*, void*); + ~ReadObjectCallback(); + + void invoke(const ::Ice::ObjectPtr&); + +private: + + ClassInfoPtr _info; + UnmarshalCallbackPtr _cb; + PyObject* _target; + void* _closure; +}; +typedef IceUtil::Handle<ReadObjectCallback> ReadObjectCallbackPtr; + +// +// This class assists during unmarshaling of Slice classes and exceptions. +// We attach an instance to a stream. +// +class StreamUtil +{ +public: + + StreamUtil(); + ~StreamUtil(); + + // + // Keep a reference to a ReadObjectCallback for patching purposes. + // + void add(const ReadObjectCallbackPtr&); + + // + // Keep track of object instances that have preserved slices. + // + void add(const ObjectReaderPtr&); + + // + // Updated the sliced data information for all stored object instances. + // + void updateSlicedData(); + + static void setSlicedDataMember(PyObject*, const Ice::SlicedDataPtr&); + static Ice::SlicedDataPtr getSlicedDataMember(PyObject*, ObjectMap*); + +private: + + std::vector<ReadObjectCallbackPtr> _callbacks; + std::set<ObjectReaderPtr> _readers; + static PyObject* _slicedDataType; + static PyObject* _sliceInfoType; +}; + +struct PrintObjectHistory +{ + int index; + std::map<PyObject*, int> objects; +}; + +// // Base class for type information. // class TypeInfo : public UnmarshalCallback @@ -125,8 +161,8 @@ public: // The marshal and unmarshal functions can raise Ice exceptions, and may raise // AbortMarshaling if an error occurs. // - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0) = 0; - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + virtual void marshal(PyObject*, Ice::OutputStream*, ObjectMap*, bool, const Ice::StringSeq* = 0) = 0; + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0) = 0; virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*) = 0; @@ -162,8 +198,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + virtual void marshal(PyObject*, Ice::OutputStream*, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); @@ -191,8 +227,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + virtual void marshal(PyObject*, Ice::OutputStream*, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); @@ -241,8 +277,8 @@ public: virtual bool usesClasses() const; - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + virtual void marshal(PyObject*, Ice::OutputStream*, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); @@ -282,8 +318,8 @@ public: virtual bool usesClasses() const; - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + virtual void marshal(PyObject*, Ice::OutputStream*, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); @@ -311,8 +347,8 @@ private: typedef IceUtil::Handle<SequenceMapping> SequenceMappingPtr; PyObject* getSequence(const PrimitiveInfoPtr&, PyObject*); - void marshalPrimitiveSequence(const PrimitiveInfoPtr&, PyObject*, const Ice::OutputStreamPtr&); - void unmarshalPrimitiveSequence(const PrimitiveInfoPtr&, const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, + void marshalPrimitiveSequence(const PrimitiveInfoPtr&, PyObject*, Ice::OutputStream*); + void unmarshalPrimitiveSequence(const PrimitiveInfoPtr&, Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, const SequenceMappingPtr&); public: @@ -342,8 +378,8 @@ public: virtual bool usesClasses() const; - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + virtual void marshal(PyObject*, Ice::OutputStream*, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); @@ -374,8 +410,8 @@ public: virtual bool usesClasses() const; - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + virtual void marshal(PyObject*, Ice::OutputStream*, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void unmarshaled(PyObject*, PyObject*, void*); @@ -424,8 +460,8 @@ public: virtual bool usesClasses() const; - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + virtual void marshal(PyObject*, Ice::OutputStream*, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); @@ -466,8 +502,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + virtual void marshal(PyObject*, Ice::OutputStream*, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); @@ -487,8 +523,8 @@ class ExceptionInfo : public IceUtil::Shared { public: - void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*); - PyObject* unmarshal(const Ice::InputStreamPtr&); + void marshal(PyObject*, Ice::OutputStream*, ObjectMap*); + PyObject* unmarshal(Ice::InputStream*); void print(PyObject*, IceUtilInternal::Output&); void printMembers(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); @@ -503,13 +539,13 @@ public: private: - void writeMembers(PyObject*, const Ice::OutputStreamPtr&, const DataMemberList&, ObjectMap*) const; + void writeMembers(PyObject*, Ice::OutputStream*, const DataMemberList&, ObjectMap*) const; }; // // ObjectWriter wraps a Python object for marshaling. // -class ObjectWriter : public Ice::ObjectWriter +class ObjectWriter : public Ice::Object { public: @@ -518,11 +554,12 @@ public: virtual void ice_preMarshal(); - virtual void write(const Ice::OutputStreamPtr&) const; + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); private: - void writeMembers(const Ice::OutputStreamPtr&, const DataMemberList&) const; + void writeMembers(Ice::OutputStream*, const DataMemberList&) const; PyObject* _object; ObjectMap* _map; @@ -532,7 +569,7 @@ private: // // ObjectReader unmarshals the state of an Ice object. // -class ObjectReader : public Ice::ObjectReader +class ObjectReader : public Ice::Object { public: @@ -541,7 +578,8 @@ public: virtual void ice_postUnmarshal(); - virtual void read(const Ice::InputStreamPtr&); + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); virtual ClassInfoPtr getInfo() const; @@ -559,16 +597,13 @@ private: // // ExceptionWriter wraps a Python user exception for marshaling. // -class ExceptionWriter : public Ice::UserExceptionWriter +class ExceptionWriter : public Ice::UserException { public: - ExceptionWriter(const Ice::CommunicatorPtr&, const PyObjectHandle&, const ExceptionInfoPtr& = 0); + ExceptionWriter(const PyObjectHandle&, const ExceptionInfoPtr& = 0); ~ExceptionWriter() throw(); - virtual void write(const Ice::OutputStreamPtr&) const; - virtual bool usesClasses() const; - virtual std::string ice_id() const; #ifndef ICE_CPP11_MAPPING ICE_DEPRECATED_API("ice_name() is deprecated, use ice_id() instead.") @@ -577,6 +612,16 @@ public: virtual Ice::UserException* ice_clone() const; virtual void ice_throw() const; + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); + + virtual bool __usesClasses() const; + +protected: + + virtual void __writeImpl(Ice::OutputStream*) const {} + virtual void __readImpl(Ice::InputStream*) {} + private: PyObjectHandle _ex; @@ -587,16 +632,13 @@ private: // // ExceptionReader creates a Python user exception and unmarshals it. // -class ExceptionReader : public Ice::UserExceptionReader +class ExceptionReader : public Ice::UserException { public: - ExceptionReader(const Ice::CommunicatorPtr&, const ExceptionInfoPtr&); + ExceptionReader(const ExceptionInfoPtr&); ~ExceptionReader() throw(); - virtual void read(const Ice::InputStreamPtr&) const; - virtual bool usesClasses() const; - virtual std::string ice_id() const; #ifndef ICE_CPP11_MAPPING ICE_DEPRECATED_API("ice_name() is deprecated, use ice_id() instead.") @@ -605,10 +647,23 @@ public: virtual Ice::UserException* ice_clone() const; virtual void ice_throw() const; + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); + + virtual bool __usesClasses() const; + PyObject* getException() const; // Borrowed reference. Ice::SlicedDataPtr getSlicedData() const; + using Ice::UserException::__read; + using Ice::UserException::__write; + +protected: + + virtual void __writeImpl(Ice::OutputStream*) const {} + virtual void __readImpl(Ice::InputStream*) {} + private: ExceptionInfoPtr _info; diff --git a/python/modules/IcePy/Util.h b/python/modules/IcePy/Util.h index 5732a9d10df..c8e33a84313 100644 --- a/python/modules/IcePy/Util.h +++ b/python/modules/IcePy/Util.h @@ -16,7 +16,7 @@ #include <Ice/Exception.h> // -// These macros replace Py_RETURN_FALSE and Py_RETURN TRUE. We use these +// These macros replace Py_RETURN_FALSE and Py_RETURN_TRUE. We use these // instead of the standard ones in order to avoid GCC warnings about // strict aliasing and type punning. // diff --git a/python/modules/IcePy/ValueFactoryManager.cpp b/python/modules/IcePy/ValueFactoryManager.cpp new file mode 100644 index 00000000000..b3e2bd43513 --- /dev/null +++ b/python/modules/IcePy/ValueFactoryManager.cpp @@ -0,0 +1,536 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifdef _WIN32 +# include <IceUtil/Config.h> +#endif +#include <ValueFactoryManager.h> +#include <Thread.h> +#include <Types.h> +#include <Ice/LocalException.h> + +using namespace std; +using namespace IcePy; + +namespace IcePy +{ + +struct ValueFactoryManagerObject +{ + PyObject_HEAD + ValueFactoryManagerPtr* vfm; +}; + +} + +namespace +{ + +ClassInfoPtr +getClassInfo(const string& id) +{ + ClassInfoPtr info; + + if(id == Ice::Object::ice_staticId()) + { + // + // When the ID is that of Ice::Object, it indicates that the stream has not + // found a factory and is providing us an opportunity to preserve the object. + // + info = lookupClassInfo("::Ice::UnknownSlicedObject"); + } + else + { + info = lookupClassInfo(id); + } + + return info; +} + +} + +IcePy::ValueFactoryManager::ValueFactoryManager() +{ + // + // Create a Python wrapper around this object. Note that this is cyclic - we clear the + // reference in destroy(). + // + ValueFactoryManagerObject* obj = reinterpret_cast<ValueFactoryManagerObject*>( + ValueFactoryManagerType.tp_alloc(&ValueFactoryManagerType, 0)); + assert(obj); + obj->vfm = new ValueFactoryManagerPtr(this); + _self = reinterpret_cast<PyObject*>(obj); + + _defaultFactory = new DefaultValueFactory; +} + +IcePy::ValueFactoryManager::~ValueFactoryManager() +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + Py_XDECREF(_self); +} + +void +IcePy::ValueFactoryManager::add(const Ice::ValueFactoryPtr& f, const string& id) +{ + Lock lock(*this); + + if(id.empty()) + { + if(_defaultFactory->getDelegate()) + { + throw Ice::AlreadyRegisteredException(__FILE__, __LINE__, "value factory", id); + } + + _defaultFactory->setDelegate(f); + } + else + { + FactoryMap::iterator p = _factories.find(id); + if(p != _factories.end()) + { + throw Ice::AlreadyRegisteredException(__FILE__, __LINE__, "value factory", id); + } + + _factories.insert(FactoryMap::value_type(id, f)); + } +} + +Ice::ValueFactoryPtr +IcePy::ValueFactoryManager::find(const string& id) const +{ + Lock lock(*this); + + if(id.empty()) + { + return _defaultFactory; + } + + FactoryMap::const_iterator p = _factories.find(id); + if(p != _factories.end()) + { + return p->second; + } + + return 0; +} + +void +IcePy::ValueFactoryManager::add(PyObject* valueFactory, PyObject* objectFactory, const string& id) +{ + try + { + add(new FactoryWrapper(valueFactory, objectFactory), id); + } + catch(const Ice::Exception& ex) + { + setPythonException(ex); + } +} + +PyObject* +IcePy::ValueFactoryManager::findValueFactory(const string& id) const +{ + Ice::ValueFactoryPtr f = find(id); + if(f) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(f); + if(w) + { + return w->getValueFactory(); + } + } + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* +IcePy::ValueFactoryManager::findObjectFactory(const string& id) const +{ + Ice::ValueFactoryPtr f = find(id); + if(f) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(f); + if(w) + { + return w->getObjectFactory(); + } + } + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* +IcePy::ValueFactoryManager::getObject() const +{ + Py_INCREF(_self); + return _self; +} + +void +IcePy::ValueFactoryManager::destroy() +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + FactoryMap factories; + + { + Lock lock(*this); + + // + // Break the cyclic reference. + // + Py_DECREF(_self); + _self = 0; + + factories.swap(_factories); + } + + for(FactoryMap::iterator p = factories.begin(); p != factories.end(); ++p) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(p->second); + if(w) + { + w->destroy(); + } + } + + _defaultFactory->destroy(); +} + +IcePy::FactoryWrapper::FactoryWrapper(PyObject* valueFactory, PyObject* objectFactory) : + _valueFactory(valueFactory), + _objectFactory(objectFactory) +{ + Py_INCREF(_valueFactory); + Py_INCREF(_objectFactory); + assert(_valueFactory != Py_None); // This should always be present. +} + +IcePy::FactoryWrapper::~FactoryWrapper() +{ + Py_DECREF(_valueFactory); + Py_DECREF(_objectFactory); +} + +Ice::ValuePtr +IcePy::FactoryWrapper::create(const string& id) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + // + // Get the type information. + // + ClassInfoPtr info = getClassInfo(id); + + if(!info) + { + return 0; + } + + PyObjectHandle obj = PyObject_CallFunction(_valueFactory, STRCAST("s"), id.c_str()); + + if(!obj.get()) + { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } + + if(obj.get() == Py_None) + { + return 0; + } + + return new ObjectReader(obj.get(), info); +} + +PyObject* +IcePy::FactoryWrapper::getValueFactory() const +{ + Py_INCREF(_valueFactory); + return _valueFactory; +} + +PyObject* +IcePy::FactoryWrapper::getObjectFactory() const +{ + Py_INCREF(_objectFactory); + return _objectFactory; +} + +void +IcePy::FactoryWrapper::destroy() +{ + if(_objectFactory != Py_None) + { + PyObjectHandle obj = PyObject_CallMethod(_objectFactory, STRCAST("destroy"), 0); + PyErr_Clear(); // Ignore errors. + } +} + +Ice::ValuePtr +IcePy::DefaultValueFactory::create(const string& id) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + Ice::ValuePtr v; + + // + // Give the application-provided default factory a chance to create the object first. + // + if(_delegate) + { + v = _delegate->create(id); + if(v) + { + return v; + } + } + + // + // Get the type information. + // + ClassInfoPtr info = getClassInfo(id); + + if(!info) + { + return 0; + } + + // + // If the requested type is an abstract class, then we give up. + // + if(info->isAbstract) + { + return 0; + } + + // + // Instantiate the object. + // + PyTypeObject* type = reinterpret_cast<PyTypeObject*>(info->pythonType.get()); + PyObjectHandle args = PyTuple_New(0); + PyObjectHandle obj = type->tp_new(type, args.get(), 0); + if(!obj.get()) + { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } + + return new ObjectReader(obj.get(), info); +} + +void +IcePy::DefaultValueFactory::setDelegate(const Ice::ValueFactoryPtr& d) +{ + _delegate = d; +} + +PyObject* +IcePy::DefaultValueFactory::getValueFactory() const +{ + if(_delegate) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(_delegate); + if(w) + { + return w->getValueFactory(); + } + } + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* +IcePy::DefaultValueFactory::getObjectFactory() const +{ + if(_delegate) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(_delegate); + if(w) + { + return w->getObjectFactory(); + } + } + + Py_INCREF(Py_None); + return Py_None; +} + +void +IcePy::DefaultValueFactory::destroy() +{ + if(_delegate) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(_delegate); + if(w) + { + w->destroy(); + } + } + + _delegate = 0; +} + +#ifdef WIN32 +extern "C" +#endif +static ValueFactoryManagerObject* +valueFactoryManagerNew(PyTypeObject* /*type*/, PyObject* /*args*/, PyObject* /*kwds*/) +{ + PyErr_Format(PyExc_RuntimeError, STRCAST("Do not instantiate this object directly")); + return 0; +} + +#ifdef WIN32 +extern "C" +#endif +static void +valueFactoryManagerDealloc(ValueFactoryManagerObject* self) +{ + delete self->vfm; + Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* +valueFactoryManagerAdd(ValueFactoryManagerObject* self, PyObject* args) +{ + assert(self->vfm); + + PyObject* factoryType = lookupType("types.FunctionType"); + assert(factoryType); + + PyObject* factory; + PyObject* idObj; + if(!PyArg_ParseTuple(args, STRCAST("O!O"), factoryType, &factory, &idObj)) + { + return 0; + } + + string id; + if(!getStringArg(idObj, "id", id)) + { + return 0; + } + + (*self->vfm)->add(factory, Py_None, id); + if(PyErr_Occurred()) + { + return 0; + } + + Py_INCREF(Py_None); + return Py_None; +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* +valueFactoryManagerFind(ValueFactoryManagerObject* self, PyObject* args) +{ + assert(self->vfm); + + PyObject* idObj; + if(!PyArg_ParseTuple(args, STRCAST("O"), &idObj)) + { + return 0; + } + + string id; + if(!getStringArg(idObj, "id", id)) + { + return 0; + } + + return (*self->vfm)->findValueFactory(id); +} + +static PyMethodDef ValueFactoryManagerMethods[] = +{ + { STRCAST("add"), reinterpret_cast<PyCFunction>(valueFactoryManagerAdd), METH_VARARGS, + PyDoc_STR(STRCAST("add(factory, id) -> None")) }, + { STRCAST("find"), reinterpret_cast<PyCFunction>(valueFactoryManagerFind), METH_VARARGS, + PyDoc_STR(STRCAST("find(id) -> function")) }, + { 0, 0 } /* sentinel */ +}; + +namespace IcePy +{ + +PyTypeObject ValueFactoryManagerType = +{ + /* 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.ValueFactoryManager"), /* tp_name */ + sizeof(ValueFactoryManagerObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + reinterpret_cast<destructor>(valueFactoryManagerDealloc), /* 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 */ + 0, /* 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 */ + ValueFactoryManagerMethods, /* 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 */ + reinterpret_cast<newfunc>(valueFactoryManagerNew), /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +} + +bool +IcePy::initValueFactoryManager(PyObject* module) +{ + if(PyType_Ready(&ValueFactoryManagerType) < 0) + { + return false; + } + PyTypeObject* type = &ValueFactoryManagerType; // Necessary to prevent GCC's strict-alias warnings. + if(PyModule_AddObject(module, STRCAST("ValueFactoryManager"), reinterpret_cast<PyObject*>(type)) < 0) + { + return false; + } + + return true; +} diff --git a/python/modules/IcePy/ValueFactoryManager.h b/python/modules/IcePy/ValueFactoryManager.h new file mode 100644 index 00000000000..78f9c804565 --- /dev/null +++ b/python/modules/IcePy/ValueFactoryManager.h @@ -0,0 +1,95 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPY_VALUE_FACTORY_MANAGER_H +#define ICEPY_VALUE_FACTORY_MANAGER_H + +#include <Config.h> +#include <Ice/ValueFactory.h> +#include <IceUtil/Mutex.h> + +namespace IcePy +{ + +extern PyTypeObject ValueFactoryManagerType; + +bool initValueFactoryManager(PyObject*); + +class FactoryWrapper : public Ice::ValueFactory +{ +public: + + FactoryWrapper(PyObject*, PyObject*); + ~FactoryWrapper(); + + virtual Ice::ValuePtr create(const std::string&); + + PyObject* getValueFactory() const; + PyObject* getObjectFactory() const; + + void destroy(); + +protected: + + PyObject* _valueFactory; + PyObject* _objectFactory; +}; +typedef IceUtil::Handle<FactoryWrapper> FactoryWrapperPtr; + +class DefaultValueFactory : public Ice::ValueFactory +{ +public: + + virtual Ice::ValuePtr create(const std::string&); + + void setDelegate(const Ice::ValueFactoryPtr&); + Ice::ValueFactoryPtr getDelegate() const { return _delegate; } + + PyObject* getValueFactory() const; + PyObject* getObjectFactory() const; + + void destroy(); + +private: + + Ice::ValueFactoryPtr _delegate; +}; +typedef IceUtil::Handle<DefaultValueFactory> DefaultValueFactoryPtr; + +class ValueFactoryManager : public Ice::ValueFactoryManager, public IceUtil::Mutex +{ +public: + + ValueFactoryManager(); + ~ValueFactoryManager(); + + virtual void add(const Ice::ValueFactoryPtr&, const std::string&); + virtual Ice::ValueFactoryPtr find(const std::string&) const; + + virtual void add(PyObject*, PyObject*, const std::string&); + PyObject* findValueFactory(const std::string&) const; + PyObject* findObjectFactory(const std::string&) const; + + PyObject* getObject() const; + + void destroy(); + +private: + + typedef std::map<std::string, Ice::ValueFactoryPtr> FactoryMap; + + PyObject* _self; + FactoryMap _factories; + DefaultValueFactoryPtr _defaultFactory; +}; +typedef IceUtil::Handle<ValueFactoryManager> ValueFactoryManagerPtr; + +} + +#endif |