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