diff options
author | Mark Spruiell <mes@zeroc.com> | 2004-09-14 13:49:45 +0000 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2004-09-14 13:49:45 +0000 |
commit | 8b5ec26a6d03924ce55c044daeccf9a7630a6b97 (patch) | |
tree | 4f2a85403f50199be4c10fb456c179024d5bb796 /py/modules/IcePy/Operation.cpp | |
parent | revising handleSystemExit (diff) | |
download | ice-8b5ec26a6d03924ce55c044daeccf9a7630a6b97.tar.bz2 ice-8b5ec26a6d03924ce55c044daeccf9a7630a6b97.tar.xz ice-8b5ec26a6d03924ce55c044daeccf9a7630a6b97.zip |
new scheme for type definitions; adding AMD support
Diffstat (limited to 'py/modules/IcePy/Operation.cpp')
-rw-r--r-- | py/modules/IcePy/Operation.cpp | 845 |
1 files changed, 534 insertions, 311 deletions
diff --git a/py/modules/IcePy/Operation.cpp b/py/modules/IcePy/Operation.cpp index e43647982ee..b93529b62d0 100644 --- a/py/modules/IcePy/Operation.cpp +++ b/py/modules/IcePy/Operation.cpp @@ -14,6 +14,7 @@ #include <Util.h> #include <Ice/Communicator.h> #include <Ice/IdentityUtil.h> +#include <Ice/IncomingAsync.h> #include <Ice/Initialize.h> #include <Ice/LocalException.h> #include <Ice/ObjectAdapter.h> @@ -46,13 +47,18 @@ public: virtual PyObject* invoke(const Ice::ObjectPrx&, const Ice::CommunicatorPtr&, PyObject*, PyObject*); virtual PyObject* invokeAsync(const Ice::ObjectPrx&, const Ice::CommunicatorPtr&, PyObject*, PyObject*, PyObject*); - virtual bool dispatch(PyObject*, const vector<Ice::Byte>&, vector<Ice::Byte>&, const Ice::Current&); + virtual void dispatch(PyObject*, const Ice::AMD_Object_ice_invokePtr&, const vector<Ice::Byte>&, + const Ice::Current&); void responseAsync(PyObject*, bool, const vector<Ice::Byte>&, const Ice::CommunicatorPtr&); void responseAsyncException(PyObject*, PyObject*); + void sendResponse(const Ice::AMD_Object_ice_invokePtr&, PyObject*, const Ice::CommunicatorPtr&); + void sendException(const Ice::AMD_Object_ice_invokePtr&, PyObject*, const Ice::CommunicatorPtr&); + std::string name; Ice::OperationMode mode; + bool amd; ParamInfoList inParams; ParamInfoList outParams; ParamInfoPtr returnType; @@ -62,7 +68,6 @@ private: bool prepareRequest(const Ice::CommunicatorPtr&, PyObject*, vector<Ice::Byte>&); PyObject* unmarshalResults(const vector<Ice::Byte>&, const Ice::CommunicatorPtr&); - bool checkDispatchException(vector<Ice::Byte>&, const Ice::CommunicatorPtr&); PyObject* unmarshalException(const std::vector<Ice::Byte>&, const Ice::CommunicatorPtr&); bool validateException(PyObject*) const; }; @@ -73,6 +78,7 @@ class AMICallback : public Ice::AMI_Object_ice_invoke public: AMICallback(const OperationIPtr&, const Ice::CommunicatorPtr&, PyObject*); + ~AMICallback(); virtual void ice_response(bool, const vector<Ice::Byte>&); virtual void ice_exception(const Ice::Exception&); @@ -81,7 +87,7 @@ private: OperationIPtr _op; Ice::CommunicatorPtr _communicator; - PyObjectHandle _callback; + PyObject* _callback; }; struct OperationObject @@ -90,10 +96,267 @@ struct OperationObject OperationPtr* op; }; +struct AMDCallbackObject +{ + PyObject_HEAD + OperationIPtr* op; + Ice::CommunicatorPtr* communicator; + Ice::AMD_Object_ice_invokePtr* cb; +}; + extern PyTypeObject OperationType; +extern PyTypeObject AMDCallbackType; } +#ifdef WIN32 +extern "C" +#endif +static OperationObject* +operationNew(PyObject* /*arg*/) +{ + OperationObject* self = PyObject_New(OperationObject, &OperationType); + if (self == NULL) + { + return NULL; + } + self->op = 0; + return self; +} + +#ifdef WIN32 +extern "C" +#endif +static int +operationInit(OperationObject* self, PyObject* args, PyObject* /*kwds*/) +{ + char* name; + PyObject* modeType = lookupType("Ice.OperationMode"); + assert(modeType != NULL); + PyObject* mode; + int amd; + PyObject* inParams; + PyObject* outParams; + PyObject* returnType; + PyObject* exceptions; + if(!PyArg_ParseTuple(args, "sO!iO!O!OO!", &name, modeType, &mode, &amd, &PyTuple_Type, &inParams, + &PyTuple_Type, &outParams, &returnType, &PyTuple_Type, &exceptions)) + { + return -1; + } + + OperationIPtr op = new OperationI; + + op->name = name; + op->amd = amd ? true : false; + + // + // mode + // + PyObjectHandle modeValue = PyObject_GetAttrString(mode, "value"); + assert(PyInt_Check(modeValue.get())); + op->mode = (Ice::OperationMode)static_cast<int>(PyInt_AS_LONG(modeValue.get())); + + // + // inParams + // + int i, sz; + sz = PyTuple_GET_SIZE(inParams); + for(i = 0; i < sz; ++i) + { + ParamInfoPtr param = new ParamInfo; + param->type = getType(PyTuple_GET_ITEM(inParams, i)); + op->inParams.push_back(param); + } + + // + // outParams + // + sz = PyTuple_GET_SIZE(outParams); + for(i = 0; i < sz; ++i) + { + ParamInfoPtr param = new ParamInfo; + param->type = getType(PyTuple_GET_ITEM(outParams, i)); + op->outParams.push_back(param); + } + + // + // returnType + // + if(returnType != Py_None) + { + op->returnType = new ParamInfo; + op->returnType->type = getType(returnType); + } + + // + // exceptions + // + sz = PyTuple_GET_SIZE(exceptions); + for(i = 0; i < sz; ++i) + { + op->exceptions.push_back(getException(PyTuple_GET_ITEM(exceptions, i))); + } + + self->op = new OperationPtr(op); + + return 0; +} + +#ifdef WIN32 +extern "C" +#endif +static void +operationDealloc(OperationObject* self) +{ + delete self->op; + PyObject_Del(self); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* +operationInvoke(OperationObject* self, PyObject* args) +{ + PyObject* pyProxy; + PyObject* opArgs; + PyObject* ctx; + if(!PyArg_ParseTuple(args, "O!O!O", &ProxyType, &pyProxy, &PyTuple_Type, &opArgs, &ctx)) + { + return NULL; + } + + if(ctx != Py_None && !PyDict_Check(ctx)) + { + PyErr_Format(PyExc_ValueError, "context argument must be None or a dictionary"); + return NULL; + } + + Ice::ObjectPrx prx = getProxy(pyProxy); + Ice::CommunicatorPtr communicator = getProxyCommunicator(pyProxy); + + assert(self->op); + return (*self->op)->invoke(prx, communicator, opArgs, ctx); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* +operationInvokeAsync(OperationObject* self, PyObject* args) +{ + PyObject* pyProxy; + PyObject* cb; + PyObject* opArgs; + PyObject* ctx; + if(!PyArg_ParseTuple(args, "O!OO!O", &ProxyType, &pyProxy, &cb, &PyTuple_Type, &opArgs, &ctx)) + { + return NULL; + } + + if(ctx != Py_None && !PyDict_Check(ctx)) + { + PyErr_Format(PyExc_ValueError, "context argument must be None or a dictionary"); + return NULL; + } + + Ice::ObjectPrx prx = getProxy(pyProxy); + Ice::CommunicatorPtr communicator = getProxyCommunicator(pyProxy); + + assert(self->op); + return (*self->op)->invokeAsync(prx, communicator, cb, opArgs, ctx); +} + +#ifdef WIN32 +extern "C" +#endif +static AMDCallbackObject* +amdCallbackNew(PyObject* /*arg*/) +{ + AMDCallbackObject* self = PyObject_New(AMDCallbackObject, &AMDCallbackType); + if (self == NULL) + { + return NULL; + } + self->op = 0; + self->communicator = 0; + self->cb = 0; + return self; +} + +#ifdef WIN32 +extern "C" +#endif +static void +amdCallbackDealloc(AMDCallbackObject* self) +{ + delete self->op; + delete self->communicator; + delete self->cb; + PyObject_Del(self); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* +amdCallbackIceResponse(AMDCallbackObject* self, PyObject* args) +{ + try + { + assert(self->op); + (*self->op)->sendResponse(*self->cb, args, *self->communicator); + } + catch(const Ice::Exception& ex) + { + (*self->cb)->ice_exception(ex); + } + catch(...) + { + // + // No exceptions should propagate to Python. + // + assert(false); + } + + Py_INCREF(Py_None); + return Py_None; +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* +amdCallbackIceException(AMDCallbackObject* self, PyObject* args) +{ + PyObject* ex; + if(!PyArg_ParseTuple(args, "O", &ex)) + { + return NULL; + } + + try + { + assert(self->op); + (*self->op)->sendException(*self->cb, ex, *self->communicator); + } + catch(const Ice::Exception& ex) + { + (*self->cb)->ice_exception(ex); + } + catch(...) + { + // + // No exceptions should propagate to Python. + // + assert(false); + } + + Py_INCREF(Py_None); + return Py_None; +} + // // Operation implementation. // @@ -120,7 +383,14 @@ IcePy::AMICallback::AMICallback(const OperationIPtr& op, const Ice::Communicator PyObject* callback) : _op(op), _communicator(communicator), _callback(callback) { - Py_INCREF(callback); + Py_INCREF(_callback); +} + +IcePy::AMICallback::~AMICallback() +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + Py_DECREF(_callback); } void @@ -128,7 +398,7 @@ IcePy::AMICallback::ice_response(bool ok, const vector<Ice::Byte>& result) { AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - _op->responseAsync(_callback.get(), ok, result, _communicator); + _op->responseAsync(_callback, ok, result, _communicator); } void @@ -138,7 +408,7 @@ IcePy::AMICallback::ice_exception(const Ice::Exception& ex) PyObjectHandle exh = convertException(ex); assert(exh.get() != NULL); - _op->responseAsyncException(_callback.get(), exh.get()); + _op->responseAsyncException(_callback, exh.get()); } // @@ -305,9 +575,9 @@ IcePy::OperationI::invokeAsync(const Ice::ObjectPrx& proxy, const Ice::Communica return Py_None; } -bool -IcePy::OperationI::dispatch(PyObject* servant, const std::vector<Ice::Byte>& inBytes, - std::vector<Ice::Byte>& outBytes, const Ice::Current& current) +void +IcePy::OperationI::dispatch(PyObject* servant, const Ice::AMD_Object_ice_invokePtr& cb, + const std::vector<Ice::Byte>& inBytes, const Ice::Current& current) { string fixedName = fixIdent(current.operation); Ice::CommunicatorPtr communicator = current.adapter->getCommunicator(); @@ -315,8 +585,16 @@ IcePy::OperationI::dispatch(PyObject* servant, const std::vector<Ice::Byte>& inB // // Unmarshal the in parameters. // - int count = static_cast<int>(inParams.size()); - PyObjectHandle args = PyTuple_New(count + 1); // Leave room for a trailing Ice::Current object. + int count = static_cast<int>(inParams.size()) + 1; // Leave room for a trailing Ice::Current object. + + int start = 0; + if(amd) + { + ++count; // Leave room for a leading AMD callback argument. + start = 1; + } + + PyObjectHandle args = PyTuple_New(count); if(args.get() == NULL) { throwPythonException(); @@ -326,7 +604,7 @@ IcePy::OperationI::dispatch(PyObject* servant, const std::vector<Ice::Byte>& inB try { - int i = 0; + int i = start; for(ParamInfoList::iterator p = inParams.begin(); p != inParams.end(); ++p, ++i) { (*p)->type->unmarshal(is, *p, args.get(), (void*)i); @@ -348,15 +626,41 @@ IcePy::OperationI::dispatch(PyObject* servant, const std::vector<Ice::Byte>& inB } curr.release(); // PyTuple_SET_ITEM steals a reference. + string methodName; + if(amd) + { + methodName = fixedName + "_async"; + // + // Create the callback object and pass it as the first argument. + // + AMDCallbackObject* obj = amdCallbackNew(NULL); + if(obj == NULL) + { + throwPythonException(); + } + obj->op = new OperationIPtr(this); + obj->communicator = new Ice::CommunicatorPtr(communicator); + obj->cb = new Ice::AMD_Object_ice_invokePtr(cb); + if(PyTuple_SET_ITEM(args.get(), 0, (PyObject*)obj) < 0) // PyTuple_SET_ITEM steals a reference. + { + Py_DECREF(obj); + throwPythonException(); + } + } + else + { + methodName = fixedName; + } + // // Dispatch the operation. Use fixedName here, not current.operation. // - PyObjectHandle method = PyObject_GetAttrString(servant, const_cast<char*>(fixedName.c_str())); + PyObjectHandle method = PyObject_GetAttrString(servant, const_cast<char*>(methodName.c_str())); if(method.get() == NULL) { ostringstream ostr; ostr << "servant for identity " << Ice::identityToString(current.id) << " does not define operation `" - << fixedName << "'"; + << methodName << "'"; string str = ostr.str(); PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); Ice::UnknownException ex(__FILE__, __LINE__); @@ -369,11 +673,101 @@ IcePy::OperationI::dispatch(PyObject* servant, const std::vector<Ice::Byte>& inB // // Check for exceptions. // - if(checkDispatchException(outBytes, communicator)) + if(PyErr_Occurred()) { - return false; + PyObjectHandle ex = getPythonException(); // Retrieve it before another Python API call clears it. + sendException(cb, ex.get(), communicator); + return; + } + + if(!amd) + { + sendResponse(cb, result.get(), communicator); + } +} + +void +IcePy::OperationI::responseAsync(PyObject* callback, bool ok, const vector<Ice::Byte>& results, + const Ice::CommunicatorPtr& communicator) +{ + try + { + if(ok) + { + // + // Unmarshal the results. + // + PyObjectHandle args = unmarshalResults(results, communicator); + if(args.get() == NULL) + { + assert(PyErr_Occurred()); + PyErr_Print(); + return; + } + + PyObjectHandle method = PyObject_GetAttrString(callback, "ice_response"); + if(method.get() == NULL) + { + ostringstream ostr; + ostr << "AMI callback object for operation `" << name << "' does not define ice_response()"; + string str = ostr.str(); + PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + } + else + { + PyObjectHandle tmp = PyObject_Call(method.get(), args.get(), NULL); + if(PyErr_Occurred()) + { + PyErr_Print(); + } + } + } + else + { + PyObjectHandle ex = unmarshalException(results, communicator); + responseAsyncException(callback, ex.get()); + } } + catch(const AbortMarshaling&) + { + assert(PyErr_Occurred()); + PyErr_Print(); + } + catch(const Ice::Exception& ex) + { + ostringstream ostr; + ostr << "Exception occurred during AMI response for operation `" << name << "':" << ex; + string str = ostr.str(); + PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + } +} + +void +IcePy::OperationI::responseAsyncException(PyObject* callback, PyObject* ex) +{ + PyObjectHandle method = PyObject_GetAttrString(callback, "ice_exception"); + if(method.get() == NULL) + { + ostringstream ostr; + ostr << "AMI callback object for operation `" << name << "' does not define ice_exception()"; + string str = ostr.str(); + PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + } + else + { + PyObjectHandle args = Py_BuildValue("(O)", ex); + PyObjectHandle tmp = PyObject_Call(method.get(), args.get(), NULL); + if(PyErr_Occurred()) + { + PyErr_Print(); + } + } +} +void +IcePy::OperationI::sendResponse(const Ice::AMD_Object_ice_invokePtr& cb, PyObject* args, + const Ice::CommunicatorPtr& communicator) +{ // // 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, ...). @@ -385,7 +779,7 @@ IcePy::OperationI::dispatch(PyObject* servant, const std::vector<Ice::Byte>& inB int numResults = static_cast<int>(outParams.size()) + i; if(numResults > 1) { - if(!PyTuple_Check(result.get()) || PyTuple_GET_SIZE(result.get()) != numResults) + if(!PyTuple_Check(args) || PyTuple_GET_SIZE(args) != numResults) { ostringstream ostr; ostr << "operation `" << fixIdent(name) << "' should return a tuple of length " << numResults; @@ -400,22 +794,24 @@ IcePy::OperationI::dispatch(PyObject* servant, const std::vector<Ice::Byte>& inB for(ParamInfoList::iterator p = outParams.begin(); p != outParams.end(); ++p, ++i) { PyObject* arg; - if(numResults > 1) + if(amd || numResults > 1) { - arg = PyTuple_GET_ITEM(result.get(), i); + arg = PyTuple_GET_ITEM(args, i); } else { - arg = result.get(); + arg = args; assert(outParams.size() == 1); } if(!(*p)->type->validate(arg)) { - // TODO: Provide the parameter name instead - PyErr_Format(PyExc_ValueError, "invalid value for out argument %d in operation `%s'", i + 1, - const_cast<char*>(name.c_str())); - return false; + // TODO: Provide the parameter name instead? + ostringstream ostr; + ostr << "invalid value for out argument " << (i + 1) << " in operation `" << fixIdent(name) << "'"; + string str = ostr.str(); + PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + throw Ice::MarshalException(__FILE__, __LINE__); } (*p)->type->marshal(arg, os, &objectMap); } @@ -423,109 +819,97 @@ IcePy::OperationI::dispatch(PyObject* servant, const std::vector<Ice::Byte>& inB if(returnType) { PyObject* res; - if(numResults > 1) + if(amd || numResults > 1) { - res = PyTuple_GET_ITEM(result.get(), 0); + res = PyTuple_GET_ITEM(args, 0); } else { assert(outParams.size() == 0); - res = result.get(); + res = args; } if(!returnType->type->validate(res)) { - PyErr_Format(PyExc_AttributeError, "invalid return value for operation `%s'", - const_cast<char*>(name.c_str())); - return false; + ostringstream ostr; + ostr << "invalid return value for operation `" << fixIdent(name) << "'"; + string str = ostr.str(); + PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + throw Ice::MarshalException(__FILE__, __LINE__); } returnType->type->marshal(res, os, &objectMap); } + Ice::ByteSeq outBytes; os->finished(outBytes); + cb->ice_response(true, outBytes); } catch(const AbortMarshaling&) { throwPythonException(); } - - return true; } void -IcePy::OperationI::responseAsync(PyObject* callback, bool ok, const vector<Ice::Byte>& results, +IcePy::OperationI::sendException(const Ice::AMD_Object_ice_invokePtr& cb, PyObject* ex, const Ice::CommunicatorPtr& communicator) { try { - if(ok) + PyObject* exType = (PyObject*)((PyInstanceObject*)ex)->in_class; + + // + // A servant that calls sys.exit() will raise the SystemExit exception. + // This is normally caught by the interpreter, causing it to exit. + // However, we have no way to pass this exception to the interpreter, + // so we act on it directly. + // + if(PyErr_GivenExceptionMatches(exType, PyExc_SystemExit)) + { + handleSystemExit(ex); // Does not return. + } + + PyObject* userExceptionType = lookupType("Ice.UserException"); + + if(PyErr_GivenExceptionMatches(exType, userExceptionType)) { // - // Unmarshal the results. + // Get the exception's id and Verify that it is legal to be thrown from this operation. // - PyObjectHandle args = unmarshalResults(results, communicator); - if(args.get() == NULL) - { - assert(PyErr_Occurred()); - PyErr_Print(); - return; - } - - PyObjectHandle method = PyObject_GetAttrString(callback, "ice_response"); - if(method.get() == NULL) + PyObjectHandle id = PyObject_CallMethod(ex, "ice_id", NULL); + PyErr_Clear(); + if(id.get() == NULL || !validateException(ex)) { - ostringstream ostr; - ostr << "AMI callback object for operation `" << name << "' does not define ice_response()"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + throwPythonException(ex); // Raises UnknownUserException. } else { - PyObjectHandle tmp = PyObject_Call(method.get(), args.get(), NULL); - if(PyErr_Occurred()) + assert(PyString_Check(id.get())); + char* str = PyString_AS_STRING(id.get()); + ExceptionInfoPtr info = lookupExceptionInfo(str); + if(!info) { - PyErr_Print(); + Ice::UnknownUserException e(__FILE__, __LINE__); + e.unknown = str; + throw e; } + + Ice::OutputStreamPtr os = Ice::createOutputStream(communicator); + ObjectMap objectMap; + info->marshal(ex, os, &objectMap); + + Ice::ByteSeq bytes; + os->finished(bytes); + cb->ice_response(false, bytes); } } else { - PyObjectHandle ex = unmarshalException(results, communicator); - responseAsyncException(callback, ex.get()); + throwPythonException(ex); } } catch(const AbortMarshaling&) { - assert(PyErr_Occurred()); - PyErr_Print(); - } - catch(const Ice::Exception& ex) - { - ostringstream ostr; - ostr << "Exception occurred during AMI response for operation `" << name << "':" << ex; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - } -} - -void -IcePy::OperationI::responseAsyncException(PyObject* callback, PyObject* ex) -{ - PyObjectHandle method = PyObject_GetAttrString(callback, "ice_exception"); - if(method.get() == NULL) - { - ostringstream ostr; - ostr << "AMI callback object for operation `" << name << "' does not define ice_exception()"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - } - else - { - PyObjectHandle args = Py_BuildValue("(O)", ex); - PyObjectHandle tmp = PyObject_Call(method.get(), args.get(), NULL); - if(PyErr_Occurred()) - { - PyErr_Print(); - } + throwPythonException(); } } @@ -613,70 +997,6 @@ IcePy::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice::C return results.release(); } -bool -IcePy::OperationI::checkDispatchException(std::vector<Ice::Byte>& bytes, const Ice::CommunicatorPtr& communicator) -{ - // - // Check for exceptions. Return true if we marshaled a user exception, or false if no - // exception was set. Local exceptions may be thrown. - // - PyObject* exType = PyErr_Occurred(); - if(exType) - { - // - // A servant that calls sys.exit() will raise the SystemExit exception. - // This is normally caught by the interpreter, causing it to exit. - // However, we have no way to pass this exception to the interpreter, - // so we act on it directly. - // - if(PyErr_GivenExceptionMatches(exType, PyExc_SystemExit)) - { - handleSystemExit(); // Does not return. - } - - PyObjectHandle ex = getPythonException(); // Retrieve it before another Python API call clears it. - - PyObject* userExceptionType = lookupType("Ice.UserException"); - - if(PyErr_GivenExceptionMatches(exType, userExceptionType)) - { - // - // Get the exception's id and Verify that it is legal to be thrown from this operation. - // - PyObjectHandle id = PyObject_CallMethod(ex.get(), "ice_id", NULL); - PyErr_Clear(); - if(id.get() == NULL || !validateException(ex.get())) - { - throwPythonException(ex.get()); // Raises UnknownUserException. - } - else - { - assert(PyString_Check(id.get())); - char* str = PyString_AS_STRING(id.get()); - ExceptionInfoPtr info = getExceptionInfo(str); - if(!info) - { - Ice::UnknownUserException e(__FILE__, __LINE__); - e.unknown = str; - throw e; - } - - Ice::OutputStreamPtr os = Ice::createOutputStream(communicator); - ObjectMap objectMap; - info->marshal(ex.get(), os, &objectMap); - os->finished(bytes); - return true; - } - } - else - { - throwPythonException(ex.get()); - } - } - - return false; -} - PyObject* IcePy::OperationI::unmarshalException(const std::vector<Ice::Byte>& bytes, const Ice::CommunicatorPtr& communicator) { @@ -687,7 +1007,7 @@ IcePy::OperationI::unmarshalException(const std::vector<Ice::Byte>& bytes, const string id = is->readString(); while(!id.empty()) { - ExceptionInfoPtr info = getExceptionInfo(id); + ExceptionInfoPtr info = lookupExceptionInfo(id); if(info) { PyObjectHandle ex = info->unmarshal(is); @@ -732,167 +1052,6 @@ IcePy::OperationI::validateException(PyObject* ex) const return false; } -#ifdef WIN32 -extern "C" -#endif -static OperationObject* -operationNew(PyObject* /*arg*/) -{ - OperationObject* self = PyObject_New(OperationObject, &OperationType); - if (self == NULL) - { - return NULL; - } - self->op = 0; - return self; -} - -#ifdef WIN32 -extern "C" -#endif -static int -operationInit(OperationObject* self, PyObject* args, PyObject* /*kwds*/) -{ - char* name; - PyObject* modeType = lookupType("Ice.OperationMode"); - assert(modeType != NULL); - PyObject* mode; - PyObject* inParams; - PyObject* outParams; - PyObject* returnType; - PyObject* exceptions; - if(!PyArg_ParseTuple(args, "sO!O!O!OO!", &name, modeType, &mode, &PyTuple_Type, &inParams, - &PyTuple_Type, &outParams, &returnType, &PyTuple_Type, &exceptions)) - { - return -1; - } - - OperationIPtr op = new OperationI; - - op->name = name; - - // - // mode - // - PyObjectHandle modeValue = PyObject_GetAttrString(mode, "value"); - assert(PyInt_Check(modeValue.get())); - op->mode = (Ice::OperationMode)static_cast<int>(PyInt_AS_LONG(modeValue.get())); - - // - // inParams - // - int i, sz; - sz = PyTuple_GET_SIZE(inParams); - for(i = 0; i < sz; ++i) - { - ParamInfoPtr param = new ParamInfo; - param->type = convertType(PyTuple_GET_ITEM(inParams, i)); - assert(param->type); - op->inParams.push_back(param); - } - - // - // outParams - // - sz = PyTuple_GET_SIZE(outParams); - for(i = 0; i < sz; ++i) - { - ParamInfoPtr param = new ParamInfo; - param->type = convertType(PyTuple_GET_ITEM(outParams, i)); - assert(param->type); - op->outParams.push_back(param); - } - - // - // returnType - // - if(returnType != Py_None) - { - op->returnType = new ParamInfo; - op->returnType->type = convertType(returnType); - } - - // - // exceptions - // - sz = PyTuple_GET_SIZE(exceptions); - for(i = 0; i < sz; ++i) - { - PyObject* s = PyTuple_GET_ITEM(exceptions, i); - assert(PyString_Check(s)); - op->exceptions.push_back(getExceptionInfo(PyString_AS_STRING(s))); - } - - self->op = new OperationPtr(op); - - return 0; -} - -#ifdef WIN32 -extern "C" -#endif -static void -operationDealloc(OperationObject* self) -{ - delete self->op; - PyObject_Del(self); -} - -#ifdef WIN32 -extern "C" -#endif -static PyObject* -operationInvoke(OperationObject* self, PyObject* args) -{ - PyObject* pyProxy; - PyObject* opArgs; - PyObject* ctx; - if(!PyArg_ParseTuple(args, "O!O!O", &ProxyType, &pyProxy, &PyTuple_Type, &opArgs, &ctx)) - { - return NULL; - } - - if(ctx != Py_None && !PyDict_Check(ctx)) - { - PyErr_Format(PyExc_ValueError, "context argument must be None or a dictionary"); - return NULL; - } - - Ice::ObjectPrx prx = getProxy(pyProxy); - Ice::CommunicatorPtr communicator = getProxyCommunicator(pyProxy); - - assert(self->op); - return (*self->op)->invoke(prx, communicator, opArgs, ctx); -} - -#ifdef WIN32 -extern "C" -#endif -static PyObject* -operationInvokeAsync(OperationObject* self, PyObject* args) -{ - PyObject* pyProxy; - PyObject* cb; - PyObject* opArgs; - PyObject* ctx; - if(!PyArg_ParseTuple(args, "O!OO!O", &ProxyType, &pyProxy, &cb, &PyTuple_Type, &opArgs, &ctx)) - { - return NULL; - } - - if(ctx != Py_None && !PyDict_Check(ctx)) - { - PyErr_Format(PyExc_ValueError, "context argument must be None or a dictionary"); - return NULL; - } - - Ice::ObjectPrx prx = getProxy(pyProxy); - Ice::CommunicatorPtr communicator = getProxyCommunicator(pyProxy); - - assert(self->op); - return (*self->op)->invokeAsync(prx, communicator, cb, opArgs, ctx); -} - static PyMethodDef OperationMethods[] = { { "invoke", (PyCFunction)operationInvoke, METH_VARARGS, PyDoc_STR("internal function") }, @@ -900,6 +1059,13 @@ static PyMethodDef OperationMethods[] = { NULL, NULL} /* sentinel */ }; +static PyMethodDef AMDCallbackMethods[] = +{ + { "ice_response", (PyCFunction)amdCallbackIceResponse, METH_VARARGS, PyDoc_STR("internal function") }, + { "ice_exception", (PyCFunction)amdCallbackIceException, METH_VARARGS, PyDoc_STR("internal function") }, + { NULL, NULL} /* sentinel */ +}; + namespace IcePy { @@ -951,6 +1117,54 @@ PyTypeObject OperationType = 0, /* tp_is_gc */ }; +PyTypeObject AMDCallbackType = +{ + /* The ob_type field must be initialized in the module init function + * to be portable to Windows without using C++. */ + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "IcePy.AMDCallback", /* tp_name */ + sizeof(AMDCallbackObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)amdCallbackDealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 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 */ + AMDCallbackMethods, /* 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 */ + (newfunc)amdCallbackNew, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + } bool @@ -965,6 +1179,15 @@ IcePy::initOperation(PyObject* module) return false; } + if(PyType_Ready(&AMDCallbackType) < 0) + { + return false; + } + if(PyModule_AddObject(module, "AMDCallback", (PyObject*)&AMDCallbackType) < 0) + { + return false; + } + return true; } |