# Patch to support Thrift as a data interchange format in the same # manner as Ice supports Google Protocol Buffers. # # Patch by: J Robert Ray jrray{_at_}imageworks{_dot_}com diff -ru ../Ice-3.4.2.orig/py/modules/IcePy/Types.cpp ./py/modules/IcePy/Types.cpp --- ../Ice-3.4.2.orig/py/modules/IcePy/Types.cpp 2011-06-15 12:44:00.000000000 -0700 +++ ./py/modules/IcePy/Types.cpp 2013-01-31 11:20:55.000000000 -0800 @@ -1877,22 +1877,55 @@ { assert(PyObject_IsInstance(p, pythonType.get()) == 1); // validate() should have caught this. - PyObjectHandle obj = PyObject_CallMethod(p, STRCAST("IsInitialized"), 0); - if(!obj.get()) - { - throwPythonException(); - } - if(!PyObject_IsTrue(obj.get())) - { - setPythonException(Ice::MarshalException(__FILE__, __LINE__, "type not fully initialized")); - throw AbortMarshaling(); + PyObjectHandle obj; + + if (thrift) { + PyObjectHandle transportOut = PyObject_Call(TMemoryBuffer.get(), emptyTuple.get(), NULL); + if (!transportOut.get()) { + throwPythonException(); + } + + PyObjectHandle tup = PyTuple_New(1); + if (!tup.get()) { + throwPythonException(); + } + Py_INCREF(transportOut.get()); + PyTuple_SET_ITEM(tup.get(), 0, transportOut.get()); + + PyObjectHandle protocolOut = PyObject_Call(TBinaryProtocol.get(), tup.get(), NULL); + if (!protocolOut.get()) { + throwPythonException(); + } + + obj = PyObject_CallMethodObjArgs(p, writeStr.get(), protocolOut.get(), NULL); + if (!obj.get()) { + throwPythonException(); + } + + obj = PyObject_CallMethodObjArgs(transportOut.get(), getvalueStr.get(), NULL); + if (!obj.get()) { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } } + else { + PyObjectHandle obj = PyObject_CallMethod(p, STRCAST("IsInitialized"), 0); + if(!obj.get()) + { + throwPythonException(); + } + if(!PyObject_IsTrue(obj.get())) + { + setPythonException(Ice::MarshalException(__FILE__, __LINE__, "type not fully initialized")); + throw AbortMarshaling(); + } - obj = PyObject_CallMethod(p, STRCAST("SerializeToString"), 0); - if(!obj.get()) - { - assert(PyErr_Occurred()); - throw AbortMarshaling(); + obj = PyObject_CallMethod(p, STRCAST("SerializeToString"), 0); + if(!obj.get()) + { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } } assert(PyString_Check(obj.get())); @@ -1913,16 +1946,10 @@ int sz = static_cast(seq.second - seq.first); // - // Create a new instance of the protobuf type. + // Create a new instance of the protobuf/thrift type. // - PyObjectHandle args = PyTuple_New(0); - if(!args.get()) - { - assert(PyErr_Occurred()); - throw AbortMarshaling(); - } PyTypeObject* type = reinterpret_cast(pythonType.get()); - PyObjectHandle p = type->tp_new(type, args.get(), 0); + PyObjectHandle p = type->tp_new(type, emptyTuple.get(), 0); if(!p.get()) { assert(PyErr_Occurred()); @@ -1932,7 +1959,7 @@ // // Initialize the object. // - PyObjectHandle obj = PyObject_CallMethod(p.get(), STRCAST("__init__"), 0, 0); + PyObjectHandle obj = PyObject_CallMethodObjArgs(p.get(), initStr.get(), NULL); if(!obj.get()) { assert(PyErr_Occurred()); @@ -1949,14 +1976,45 @@ throw AbortMarshaling(); } - // - // Parse the string. - // - obj = PyObject_CallMethod(p.get(), STRCAST("ParseFromString"), STRCAST("O"), obj.get(), 0); - if(!obj.get()) - { - assert(PyErr_Occurred()); - throw AbortMarshaling(); + if (thrift) { + PyObjectHandle tup = PyTuple_New(1); + if (!tup.get()) { + throwPythonException(); + } + PyTuple_SET_ITEM(tup.get(), 0, obj.release()); + + PyObjectHandle transportIn = PyObject_Call(TMemoryBuffer.get(), tup.get(), NULL); + if (!transportIn.get()) { + throwPythonException(); + } + + tup = PyTuple_New(1); + if (!tup.get()) { + throwPythonException(); + } + PyTuple_SET_ITEM(tup.get(), 0, transportIn.release()); + + PyObjectHandle protocolIn = PyObject_Call(TBinaryProtocol.get(), tup.get(), NULL); + if (!protocolIn.get()) { + throwPythonException(); + } + + obj = PyObject_CallMethodObjArgs(p.get(), readStr.get(), protocolIn.get(), NULL); + if (!obj.get()) { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } + } + else { + // + // Parse the string. + // + obj = PyObject_CallMethod(p.get(), STRCAST("ParseFromString"), STRCAST("O"), obj.get(), 0); + if(!obj.get()) + { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } } cb->unmarshaled(p.get(), target, closure); @@ -3213,7 +3271,8 @@ { char* id; PyObject* type; - if(!PyArg_ParseTuple(args, STRCAST("sO"), &id, &type)) + char* encoder; + if(!PyArg_ParseTuple(args, STRCAST("sOs"), &id, &type, &encoder)) { return 0; } @@ -3223,6 +3282,52 @@ CustomInfoPtr info = new CustomInfo; info->id = id; info->pythonType = type; + if (!strncmp(encoder, "thrift", 6)) { + info->thrift = true; + + PyObjectHandle TTransport = PyImport_ImportModule(STRCAST("thrift.transport.TTransport")); + if (!TTransport.get()) { + throwPythonException(); + } + info->TMemoryBuffer = PyObject_GetAttrString(TTransport.get(), STRCAST("TMemoryBuffer")); + if (!info->TMemoryBuffer.get()) { + throwPythonException(); + } + + PyObjectHandle TBinaryProtocol = PyImport_ImportModule(STRCAST("thrift.protocol.TBinaryProtocol")); + if (!TBinaryProtocol.get()) { + throwPythonException(); + } + info->TBinaryProtocol = PyObject_GetAttrString(TBinaryProtocol.get(), STRCAST("TBinaryProtocol")); + if (!info->TBinaryProtocol.get()) { + throwPythonException(); + } + + info->readStr = PyString_FromStringAndSize(STRCAST("read"), 4); + if (!info->readStr.get()) { + throwPythonException(); + } + + info->writeStr = PyString_FromStringAndSize(STRCAST("write"), 5); + if (!info->writeStr.get()) { + throwPythonException(); + } + + info->getvalueStr = PyString_FromStringAndSize(STRCAST("getvalue"), 8); + if (!info->getvalueStr.get()) { + throwPythonException(); + } + } + + info->emptyTuple = PyTuple_New(0); + if (!info->emptyTuple.get()) { + throwPythonException(); + } + + info->initStr = PyString_FromStringAndSize(STRCAST("__init__"), 8); + if (!info->initStr.get()) { + throwPythonException(); + } return createType(info); } diff -ru ../Ice-3.4.2.orig/py/modules/IcePy/Types.h ./py/modules/IcePy/Types.h --- ../Ice-3.4.2.orig/py/modules/IcePy/Types.h 2011-06-15 12:44:00.000000000 -0700 +++ ./py/modules/IcePy/Types.h 2013-01-31 11:20:55.000000000 -0800 @@ -271,6 +271,14 @@ std::string id; PyObjectHandle pythonType; + bool thrift; + PyObjectHandle TMemoryBuffer; + PyObjectHandle TBinaryProtocol; + PyObjectHandle emptyTuple; + PyObjectHandle readStr; + PyObjectHandle writeStr; + PyObjectHandle getvalueStr; + PyObjectHandle initStr; }; typedef IceUtil::Handle CustomInfoPtr;