00001
00008 #ifdef __ICC
00009
00010
00011 #pragma warning(disable:2259)
00012 #endif
00013
00014 #include "GaudiMP/PyROOTPickle.h"
00015 #include "Python.h"
00016 #include "TClass.h"
00017 #include "TClassRef.h"
00018 #include "TBufferFile.h"
00019 #include "TPython.h"
00020 #include "RVersion.h"
00021
00022
00023 #if ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
00024 static PyObject* gExpand = 0;
00025 #endif
00026
00027 namespace GaudiMP {
00028
00029 #if ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
00030
00035 PyObject* ObjectProxyReduce( PyObject* self )
00036 {
00037
00038
00039
00040
00041 void* vself = TPython::ObjectProxy_AsVoidPtr( self );
00042 if ( ! vself ) {
00043 PyErr_SetString( PyExc_TypeError,
00044 "__reduce__ requires an object proxy instance as first argument" );
00045 return 0;
00046 }
00047
00048 PyObject* nattr = PyObject_GetAttrString( (PyObject*)self->ob_type, (char*)"__name__" );
00049 PyObject* pyname = PyObject_Str( nattr );
00050 Py_DECREF( nattr );
00051
00052 static TClass* bufferclass = TClass::GetClass("TBufferFile");
00053 TClass* klass = TClass::GetClass( PyString_AS_STRING( pyname ) );
00054
00055
00056
00057 TBufferFile* buf = 0;
00058 if ( klass == bufferclass ) {
00059 buf = (TBufferFile*)vself;
00060 }
00061 else {
00062 static TBufferFile buffer( TBuffer::kWrite );
00063 buffer.Reset();
00064 if ( buffer.WriteObjectAny( vself, klass ) != 1 ) {
00065 PyErr_Format( PyExc_IOError,
00066 "could not stream object of type %s", PyString_AS_STRING( pyname ) );
00067 Py_DECREF( pyname );
00068 return 0;
00069 }
00070 buf = &buffer;
00071 }
00072
00073
00074
00075
00076 PyObject* res2 = PyTuple_New( 2 );
00077 PyTuple_SET_ITEM( res2, 0, PyString_FromStringAndSize( buf->Buffer(), buf->Length() ) );
00078 PyTuple_SET_ITEM( res2, 1, pyname );
00079
00080 PyObject* result = PyTuple_New( 2 );
00081 Py_INCREF( gExpand );
00082 PyTuple_SET_ITEM( result, 0, gExpand );
00083 PyTuple_SET_ITEM( result, 1, res2 );
00084
00085 return result;
00086 }
00087
00088
00089 class ObjectProxy {
00090 public:
00091 enum EFlags { kNone = 0x0, kIsOwner = 0x0001, kIsReference = 0x0002 };
00092
00093 public:
00094 void HoldOn() { fFlags |= kIsOwner; }
00095 void Release() { fFlags &= ~kIsOwner; }
00096 public:
00097 PyObject_HEAD
00098 void* fObject;
00099 TClassRef fClass;
00100 int fFlags;
00101 private:
00102 ObjectProxy() {}
00103 };
00104
00105
00110 PyObject* ObjectProxyExpand( PyObject*, PyObject* args )
00111 {
00112
00113 PyObject* pybuf = 0;
00114 const char* clname = 0;
00115 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!s:__expand__" ),
00116 &PyString_Type, &pybuf, &clname ) )
00117 return 0;
00118
00119
00120
00121 void* result;
00122 if( strcmp(clname, "TBufferFile") == 0) {
00123 TBufferFile* buf = new TBufferFile( TBuffer::kWrite);
00124 buf->WriteFastArray( PyString_AS_STRING(pybuf), PyString_GET_SIZE( pybuf ));
00125 result = buf;
00126 }
00127 else {
00128 TBufferFile buf( TBuffer::kRead,
00129 PyString_GET_SIZE( pybuf ), PyString_AS_STRING( pybuf ), kFALSE );
00130 result = buf.ReadObjectAny( 0 );
00131 }
00132 PyObject* pobj = TPython::ObjectProxy_FromVoidPtr( result, clname );
00133
00134 ObjectProxy* obj = (ObjectProxy*)pobj;
00135 obj->HoldOn();
00136 return pobj;
00137 }
00138
00139
00145 void PyROOTPickle::Initialize( PyObject* libpyroot_pymodule, PyObject* objectproxy_pytype )
00146 {
00147 Py_INCREF( libpyroot_pymodule );
00148 PyTypeObject* pytype = (PyTypeObject*)objectproxy_pytype;
00149
00150 static PyMethodDef s_pdefExp = { (char*)"_ObjectProxy__expand__",
00151 (PyCFunction)ObjectProxyExpand, METH_VARARGS, (char*)"internal function" };
00152
00153 PyObject* pymname = PyString_FromString( PyModule_GetName( libpyroot_pymodule ) );
00154 gExpand = PyCFunction_NewEx( &s_pdefExp, NULL, pymname );
00155 Py_DECREF( pymname );
00156 Bool_t isOk = PyObject_SetAttrString( libpyroot_pymodule, s_pdefExp.ml_name, gExpand ) == 0;
00157 Py_DECREF( gExpand );
00158
00159 if ( ! isOk ) {
00160 Py_DECREF( libpyroot_pymodule );
00161 PyErr_SetString( PyExc_TypeError, "could not add expand function to libPyROOT" );
00162 return;
00163 }
00164
00165 static PyMethodDef s_pdefRed = { (char*)"__reduce__",
00166 (PyCFunction)ObjectProxyReduce, METH_NOARGS, (char*)"internal function" };
00167
00168 PyObject* descr = PyDescr_NewMethod( pytype, &s_pdefRed );
00169 isOk = PyDict_SetItemString( pytype->tp_dict, s_pdefRed.ml_name, descr) == 0;
00170 Py_DECREF( descr );
00171 if ( ! isOk ) {
00172 Py_DECREF( libpyroot_pymodule );
00173 PyErr_SetString( PyExc_TypeError, "could not add __reduce__ function to ObjectProxy" );
00174 return;
00175 }
00176
00177 Py_DECREF( libpyroot_pymodule );
00178 }
00179
00180 #else // ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
00181
00182 void PyROOTPickle::Initialize( PyObject*, PyObject* )
00183 {
00184
00185 }
00186
00187 #endif // ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
00188
00189 }