dimcppmodule.cpp

Go to the documentation of this file.
00001 /** **************************************************************************
00002  * \brief This file creates Python wrappers for the DimRpc and DimRpcInfo
00003  * DIM classes.
00004  *
00005  * \authors M. Frank, N. Neufeld, R. Stoica
00006  * \date Nov. 2007 - September 2008
00007  *
00008  * *************************************************************************/
00009 
00010 #define DIMCPP_MODULE
00011 extern "C" {
00012 #include "Python.h"
00013 #include "structmember.h"
00014 }
00015 #include "dis.hxx"
00016 #include "dic.hxx"
00017 #include <cctype>
00018 #include <cstdlib>
00019 #include <cstdio>
00020 
00021 #include "pydim_utils.cpp"
00022 
00023 /** @addtogroup dim
00024  * @{
00025  */
00026 
00027 /****************************************************************************
00028  * DimRpc Wrapper
00029  ****************************************************************************/
00030 class DimRpcWrapper: public DimRpc
00031 /**
00032  * This class is only a proxy to pass the call from the C++ rpcHandler
00033  * function to the Python implementation. For this a reference to the
00034  * real Python object is needed.
00035  * Need to reimplement the constructor, destructor and rpcHandler
00036  */
00037 {
00038   PyObject *self; // note that self can be a derived class
00039 
00040 public:
00041   DimRpcWrapper (char *name,
00042                  char *format_in,
00043                  char *format_out,
00044                  PyObject *pyobj
00045                  ): DimRpc(name, format_in, format_out)
00046   {
00047     if (pyobj) {
00048       Py_INCREF(pyobj);
00049     }
00050     this->self = pyobj;
00051   }
00052 
00053   void rpcHandler()
00054   {
00055     /** This function is called by the DIM library and will not have
00056      * the Python interpretor lock. All Python API calls must be protected
00057      * using Ensure() and Release().
00058      */
00059     PyObject *res;
00060     PyGILState_STATE gstate;
00061 
00062     if (!this->self) {
00063       print("No 'self' Python object found. Can't call to python layer");
00064       return;
00065     } else {
00066       gstate = PyGILState_Ensure();
00067       res = PyObject_CallMethod(this->self, "rpcHandler", NULL);
00068       if (!res) {
00069         // print ("Invalid call to virtual rpcHandler method %p", res);
00070         PyErr_Print();
00071       }
00072       Py_XDECREF(res);
00073       PyGILState_Release(gstate);
00074     }
00075   }
00076 
00077   ~DimRpcWrapper()
00078   {
00079     Py_XDECREF(this->self);
00080   }
00081 
00082 }; //end DimRpcWrapper
00083 
00084 
00085 typedef struct {
00086   PyObject_HEAD;
00087   DimRpcWrapper *cpp_dimRpc;
00088   char *format_in;
00089   char *format_out;
00090 } DimRpc_Object;
00091 
00092 
00093 static void
00094 DimRpc_dealloc(DimRpc_Object *self) {
00095   /** Dealocates a DimRpc object */
00096   delete self->cpp_dimRpc;
00097   self->ob_type->tp_free((PyObject*)self);
00098 }
00099 
00100 
00101 static int
00102 DimRpc_init(DimRpc_Object *self, PyObject *args, PyObject *kwds) {
00103   /** Allocates a new DimRpc_Object and a DimRpcWrapper inside it
00104    */
00105   char *name=NULL, *format_in=NULL, *format_out=NULL;
00106   static char *kwlist[] = {"name", "format_in", "format_out", NULL};
00107 
00108   if ( !PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist,
00109                                     &name, &format_in, &format_out)
00110        ) {
00111     print("Invalid arguments. Received: %s %s %s",
00112     name, format_in, format_out);
00113     return -1;
00114   }
00115   if (!verify_dim_format(format_in) || !verify_dim_format(format_out)) {
00116     PyErr_SetString(PyExc_AttributeError, "Invalid formats specified");
00117     return -1;
00118   }
00119   self->cpp_dimRpc = new DimRpcWrapper(name, format_in, format_out,
00120                (PyObject *)self);
00121   if (!self->cpp_dimRpc) {
00122   return -1;
00123   }
00124   self->format_in  = new char[strlen(format_in)+1];
00125   self->format_out = new char[strlen(format_out)+1];
00126   strcpy(self->format_in, format_in);
00127   strcpy(self->format_out, format_out);
00128   print("Created new dimRpc proxy");
00129 
00130   return 0;
00131 }
00132 
00133 
00134 static PyObject *
00135 DimRpc_new(PyTypeObject *type, PyObject* /* args */, PyObject* /* kwds */)
00136 {
00137   /** Allocates a new DimRpc_Object and initialises the cpp_dimRpc to NULL */
00138   DimRpc_Object *self;
00139 
00140   self = (DimRpc_Object*)type->tp_alloc(type, 0);
00141   if (self != NULL) {
00142     self->cpp_dimRpc=NULL;
00143     self->format_in=NULL;
00144     self->format_out=NULL;
00145   }
00146 
00147   /* in case of errors self is NULL and the error string is already set */
00148   return (PyObject *)self;
00149 }
00150 
00151 
00152 static PyObject *
00153 DimRpc_name (DimRpc_Object *self)  {
00154 
00155   PyObject *res=NULL;
00156 
00157   if (!self->cpp_dimRpc) {
00158     // should never reach this point
00159     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00160     return NULL;
00161   }
00162   res = PyString_FromString(self->cpp_dimRpc->getName());
00163 
00164   return res; // res is a new reference and will be owned by the caller
00165 }
00166 
00167 
00168 static PyObject *DimRpc_getInt (DimRpc_Object *self)  {
00169   PyObject *res=NULL;
00170   int cpp_res=0;
00171 
00172   if (!self->cpp_dimRpc) {
00173     // should never reach this point
00174     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00175     return NULL;
00176   }
00177   cpp_res = self->cpp_dimRpc->getInt();
00178   res = PyInt_FromLong( (long)cpp_res );
00179 
00180   return res; // res is a new reference and will be owned by the caller
00181 }
00182 
00183 
00184 static PyObject *
00185 DimRpc_getFloat (DimRpc_Object *self)  {
00186   PyObject *res=NULL;
00187   float cpp_res=0;
00188 
00189   if (!self->cpp_dimRpc) {
00190     // should never reach this point
00191     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00192     return NULL;
00193   }
00194   cpp_res = self->cpp_dimRpc->getFloat();
00195   res = PyFloat_FromDouble((double)cpp_res);
00196 
00197   return res; // res is a new reference and will be owned by the caller
00198 }
00199 
00200 
00201 static PyObject *
00202 DimRpc_getDouble (DimRpc_Object *self)  {
00203   PyObject *res=NULL;
00204   double cpp_res=0;
00205 
00206   if (!self->cpp_dimRpc) {
00207     // should never reach this point
00208     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00209     return NULL;
00210   }
00211   cpp_res = self->cpp_dimRpc->getDouble();
00212   res = PyFloat_FromDouble(cpp_res);
00213 
00214   return res; // res is a new reference and will be owned by the caller
00215 }
00216 
00217 
00218 static PyObject *
00219 DimRpc_getString (DimRpc_Object *self)  {
00220   PyObject *res=NULL;
00221   char *cpp_res=NULL;
00222 
00223   if (!self->cpp_dimRpc) {
00224     // should never reach this point
00225     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00226     return NULL;
00227   }
00228   cpp_res = self->cpp_dimRpc->getString();
00229   res = PyString_FromString(cpp_res);
00230 
00231   return res; // res is a new reference and will be owned by the caller
00232 }
00233 
00234 
00235 static PyObject *
00236 DimRpc_getSize (DimRpc_Object *self)  {
00237   PyObject *res=NULL;
00238   int cpp_res=0;
00239 
00240   if (!self->cpp_dimRpc) {
00241     // should never reach this point
00242     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00243     return NULL;
00244   }
00245   cpp_res = self->cpp_dimRpc->getSize();
00246   res = PyInt_FromLong(cpp_res);
00247 
00248   return res; // res is a new reference and will be owned by the caller
00249 }
00250 
00251 
00252 static PyObject *
00253 DimRpc_getData(DimRpc_Object * self)   {
00254   PyObject *res=NULL, *tmp=NULL;
00255   char *buff=NULL;
00256   int buff_size=0;
00257 
00258   if (!self->cpp_dimRpc) {
00259     // should never reach this point
00260     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00261     return NULL;
00262   }
00263   buff = (char*)self->cpp_dimRpc->getData();
00264   buff_size = self->cpp_dimRpc->getSize();
00265   res = dim_buf_to_tuple(self->format_in, buff, buff_size);
00266   if (res && PyTuple_Size(res)==1){
00267     // in case there is only an object
00268     tmp = PyTuple_GetItem(res, 0);
00269     Py_INCREF(tmp);
00270     Py_DECREF(res);
00271     return tmp;
00272   }
00273 
00274   return res; // res is a new reference and will be owned by the caller
00275 }
00276 
00277 
00278 static PyObject *
00279 DimRpc_setData (DimRpc_Object* self, PyObject* args)  {
00280   /** Gets some Python objects and converts them to the appropiate C++ values.
00281    * The conversion is done based on the arguments supplied when the RPC
00282    * command was created.
00283    */
00284   char *buff=NULL;
00285   unsigned int buff_size=0;
00286 
00287   if (!self->cpp_dimRpc) {
00288     // should never reach this point
00289     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00290     return NULL;
00291   }
00292   if (iterator_to_allocated_buffer(args, self->format_out,
00293            (char **)&buff, &buff_size) ) {
00294     self->cpp_dimRpc->setData(buff, buff_size);
00295     delete buff;
00296   } else {
00297     PyErr_SetString(PyExc_AttributeError,
00298         "Could not convert arguments to C buffer");
00299     return NULL;
00300   }
00301 
00302   Py_RETURN_NONE;
00303 }
00304 
00305 
00306 static PyObject *DimRpc_rpcHandler (DimRpc_Object* /* self */) {
00307   print("RPC call received in C++\n");
00308   Py_RETURN_NONE;
00309 }
00310 
00311 
00312 static PyMethodDef DimRpc_methods[] = {
00313   {"name"      , (PyCFunction)DimRpc_name       , METH_NOARGS,
00314    "Returns the name of the service."                        },
00315   {"getData"   , (PyCFunction)DimRpc_getData    , METH_NOARGS,
00316    "Returns received integer data as a Python int"           },
00317   {"getInt"    , (PyCFunction)DimRpc_getInt     , METH_NOARGS,
00318    "Returns received integer data as a Python int"           },
00319   {"getDouble" , (PyCFunction)DimRpc_getDouble  , METH_NOARGS,
00320    "Returns received double data as Python float"            },
00321   {"getFloat"  , (PyCFunction)DimRpc_getFloat   , METH_NOARGS,
00322    "Returns received float data as a Python float"           },
00323   {"getString" , (PyCFunction)DimRpc_getString  , METH_NOARGS,
00324    "Returns received string data as a Python string"         },
00325   {"getSize"   , (PyCFunction)DimRpc_getSize    , METH_NOARGS,
00326    "Returns the total received data size as a Python int"    },
00327   {"setData"   , (PyCFunction)DimRpc_setData    , METH_VARARGS,
00328    "Sets results data according to the initial format string"},
00329   {"rpcHandler", (PyCFunction)DimRpc_rpcHandler , METH_NOARGS,
00330    "Dummy function for the rpcHandler part"                  },
00331   {NULL, NULL, 0, NULL}  /* Sentinel */
00332 };
00333 
00334 
00335 static PyMethodDef dimcpp_methods[] = {
00336   {NULL, NULL, 0, NULL}  /* Sentinel */
00337 };
00338 
00339 
00340 static PyTypeObject DimRpc_Type = {
00341   PyObject_HEAD_INIT(NULL)
00342   0,                          /* ob_size*/
00343   "dim.DimRpc",               /* tp_name*/
00344   sizeof(DimRpc_Object),      /* tp_basicsize*/
00345   0,                          /* tp_itemsize*/
00346   (destructor)DimRpc_dealloc, /* tp_dealloc*/
00347   0,                          /* tp_print*/
00348   0,                          /* tp_getattr*/
00349   0,                          /* tp_setattr*/
00350   0,                          /* tp_compare*/
00351   0,                          /* tp_repr*/
00352   0,                          /* tp_as_number*/
00353   0,                          /* tp_as_sequence*/
00354   0,                          /* tp_as_mapping*/
00355   0,                          /* tp_hash */
00356   0,                          /* tp_call*/
00357   0,                          /* tp_str*/
00358   0,                          /* tp_getattro*/
00359   0,                          /* tp_setattro*/
00360   0,                          /* tp_as_buffer*/
00361   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
00362   "DimRpc object",            /* tp_doc */
00363   0,                          /* tp_traverse */
00364   0,                          /* tp_clear */
00365   0,                          /* tp_richcompare */
00366   0,                          /* tp_weaklistoffset */
00367   0,                          /* tp_iter */
00368   0,                          /* tp_iternext */
00369   DimRpc_methods,             /* tp_methods */
00370   0,                          /* tp_members */
00371   0,                          /* tp_getset */
00372   0,                          /* tp_base */
00373   0,                          /* tp_dict */
00374   0,                          /* tp_descr_get */
00375   0,                          /* tp_descr_set */
00376   0,                          /* tp_dictoffset */
00377   (initproc)DimRpc_init,      /* tp_init */ /* init is the same as new */
00378   0,                          /* tp_alloc */
00379   DimRpc_new,                 /* tp_new */
00380   _PyObject_Del,              /* tp_free */
00381   0,                          /* tp_is_gc */
00382   0,                          /* tp_bases */
00383   0,                          /* tp_mro */
00384   0,                          /* tp_cache */
00385   0,                          /* tp_subclasses */
00386   0,                          /* tp_weaklist */
00387   (destructor)DimRpc_dealloc  /* tp_del */
00388 };
00389 
00390 
00391 /****************************************************************************
00392  * DimRpcInfo Wrapper
00393  * **************************************************************************/
00394 class DimRpcInfoWrapper: public DimRpcInfo
00395 /** This class is only a proxy to pass the call from the C++ rpcInfoHandler
00396  * function to the Python implementation. For this a reference to the
00397  * real Python object is needed.
00398  * Need to reimplement the constructor, destructor and rpcInfoHandler
00399  */
00400 {
00401   PyObject *self; // note that self can be a derived class
00402 
00403 public:
00404   /** it is much easier to provide a simple setter for the python object
00405    * reference rather than reimplement all 12 costructors.
00406    * This needs to be called imediatelly after the init method of the
00407    * object.
00408    */
00409   DimRpcInfoWrapper(const char *name, int time, void *nolink,
00410         int nolinksize): DimRpcInfo(name, time, nolink, nolinksize) {}
00411 
00412   DimRpcInfoWrapper(const char *name, void *nolink, int nolinksize):
00413     DimRpcInfo(name, nolink, nolinksize) {}
00414 
00415   int setPyRef (PyObject *self)
00416   {
00417     if (!self)
00418       return 0;
00419     Py_INCREF(self);
00420     this->self=self;
00421     return 1;
00422   }
00423 
00424   void rpcInfoHandler()
00425   {
00426     PyObject *res;
00427     PyGILState_STATE gstate;
00428 
00429     if (!this->self) {
00430       print("No 'self' Python object found. Can't pass the function call");
00431       return;
00432     } else {
00433       gstate = PyGILState_Ensure();
00434       res = PyObject_CallMethod(this->self, "rpcInfoHandler", NULL);
00435       if (res) {
00436         print ("Invalid call to virtual rpcInfoHandler method %p", res);
00437         PyErr_Print();
00438       } else {
00439         Py_XDECREF(res);
00440       }
00441       PyGILState_Release(gstate);
00442     }
00443   }
00444 
00445   ~DimRpcInfoWrapper()
00446   {
00447     Py_XDECREF(this->self);
00448   }
00449 
00450 }; //end DimRpcInfoWrapper
00451 
00452 typedef struct {
00453   PyObject_HEAD;
00454   DimRpcInfoWrapper *cpp_dimRpcInfo;
00455   char *format_in;
00456   char *format_out;
00457   PyObject *nolink;
00458 } DimRpcInfo_Object;
00459 
00460 static void
00461 DimRpcInfo_dealloc(DimRpcInfo_Object *self) {
00462   /** Dealocates a DimRpcInfo objet */
00463   delete self->cpp_dimRpcInfo;
00464   Py_XDECREF(self->nolink);
00465   self->ob_type->tp_free((PyObject*)self);
00466 }
00467 
00468 
00469 static int
00470 DimRpcInfo_init(DimRpcInfo_Object* self, PyObject* args, PyObject* kwds)  {
00471   /** Allocates a new DimRpcInfo_Object and a DimRpcInfoWrapper inside it.
00472    */
00473   char *name=NULL, *format_in=NULL, *format_out=NULL;
00474   PyObject *arg1=NULL, *arg2=NULL;
00475   static char *kwlist[] = {"name", "format_in", "format_out",
00476                            "time", "nolink", NULL};
00477 
00478   if (!PyArg_ParseTupleAndKeywords(args, kwds, "sssO|O", kwlist,
00479                                    &name,
00480                                    &format_in,
00481                                    &format_out,
00482                                    &arg1, &arg2)
00483      )
00484   {
00485     print("Invalid arguments for RPC Info %s", name);
00486     return -1;
00487   }
00488   if ((arg2 && !PyInt_Check(arg1)) || (!arg1))  {
00489     /* we have an unknown object as argument arg1 */
00490     print ("Invalid arguments");
00491     return -1;
00492   }
00493   /* It is useless to perform a back and forth conversion for the default
00494    * failure arguments
00495    */
00496   if (arg2 && PyInt_Check(arg2)) {
00497     /* this means we have a time argument */
00498     Py_INCREF(arg2);
00499     self->cpp_dimRpcInfo = new DimRpcInfoWrapper((const char*)name,
00500                                PyInt_AsLong(arg1), (void*)NULL, 0);
00501     self->nolink=arg2;
00502   } else {
00503     /* we don't have a time argument and arg1 is the failure param */
00504     Py_INCREF(arg1);
00505     self->cpp_dimRpcInfo = new DimRpcInfoWrapper((const char*)name,
00506                                      (void*)NULL, 0);
00507     self->nolink=arg1;
00508 
00509   }
00510   self->cpp_dimRpcInfo->setPyRef( (PyObject *)self );
00511   if (self->cpp_dimRpcInfo) {
00512     self->format_in = new char[strlen(format_in)+1];
00513     self->format_out = new char[strlen(format_out)+1];
00514     strcpy(self->format_in, format_in);
00515     strcpy(self->format_out, format_out);
00516     print("Created new dimRpcInfo proxy");
00517     return 0;
00518   }
00519 
00520   return -1;
00521 }
00522 
00523 static PyObject *DimRpcInfo_new(PyTypeObject* type, PyObject* /* args */, PyObject* /* kwds */) {
00524   /** Allocates a new DimRpcInfo_Object and initialises the cpp_dimRpcInfo to NULL
00525    */
00526   DimRpcInfo_Object *self = (DimRpcInfo_Object*)type->tp_alloc(type, 0);
00527   if (self != NULL) {
00528     self->cpp_dimRpcInfo=NULL;
00529     self->format_in=NULL;
00530     self->format_out=NULL;
00531     self->nolink=NULL;
00532   }
00533 
00534   /* in case of errors self is NULL and the error string is already set */
00535   return (PyObject *)self;
00536 }
00537 
00538 static PyObject* DimRpcInfo_name (DimRpcInfo_Object * self)  {
00539   PyObject *res=NULL;
00540 
00541   if (!self->cpp_dimRpcInfo) {
00542     // should never reach this point
00543     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00544     return NULL;
00545   }
00546   res = PyString_FromString(self->cpp_dimRpcInfo->getName());
00547 
00548   return res; // res is a new reference and will be owned by the caller
00549 }
00550 
00551 
00552 static PyObject *DimRpcInfo_getInt (DimRpcInfo_Object * self)  {
00553   PyObject *res=NULL;
00554   int *cpp_res=NULL, size;
00555 
00556   if (!self->cpp_dimRpcInfo) {
00557     // should never reach this point
00558     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00559     return NULL;
00560   }
00561   /* Making sure we don't block the other Python threads
00562    * All calls to the DIM API are potentialy blocking
00563    */
00564   Py_BEGIN_ALLOW_THREADS
00565   size = self->cpp_dimRpcInfo->getSize();
00566   Py_END_ALLOW_THREADS
00567   if (!size) {
00568       /* this means the RPC failed and we must provide the
00569        * default failure parameter
00570        */
00571       return  self->nolink;
00572   }
00573   Py_BEGIN_ALLOW_THREADS
00574   cpp_res = (int*)self->cpp_dimRpcInfo->getData();
00575   Py_END_ALLOW_THREADS
00576   res = PyInt_FromLong( (long)*cpp_res );
00577 
00578   return res; /* res is a new reference and will be owned by the caller */
00579 }
00580 
00581 
00582 static PyObject *
00583 DimRpcInfo_getFloat (DimRpcInfo_Object * self)  {
00584   PyObject *res=NULL;
00585   float *cpp_res=NULL;
00586   int size;
00587 
00588   if (!self->cpp_dimRpcInfo) {
00589     // should never reach this point
00590     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00591     return NULL;
00592   }
00593   /* Making sure we don't block the other Python threads
00594    * All calls to the DIM API are potentialy blocking
00595    */
00596   Py_BEGIN_ALLOW_THREADS
00597   size = self->cpp_dimRpcInfo->getSize();
00598   Py_END_ALLOW_THREADS
00599   if (!size) {
00600     /* this means the RPC failed and we must provide the
00601      * default failure parameter
00602      */
00603     return self->nolink;
00604   }
00605   Py_BEGIN_ALLOW_THREADS
00606   cpp_res = (float*)self->cpp_dimRpcInfo->getData();
00607   Py_END_ALLOW_THREADS
00608   res = PyFloat_FromDouble( (double)*cpp_res );
00609 
00610   return res; /* res is a new reference and will be owned by the caller */
00611 }
00612 
00613 
00614 static PyObject *
00615 DimRpcInfo_getDouble (DimRpcInfo_Object * self) {
00616   PyObject *res=NULL;
00617   double *cpp_res=NULL;
00618   int size;
00619 
00620   if (!self->cpp_dimRpcInfo) {
00621     // should never reach this point
00622     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00623     return NULL;
00624   }
00625   /* Making sure we don't block the other Python threads
00626    * All calls to the DIM API are potentialy blocking
00627    */
00628   Py_BEGIN_ALLOW_THREADS
00629   size = self->cpp_dimRpcInfo->getSize();
00630   Py_END_ALLOW_THREADS
00631   if (!size) {
00632     /* this means the RPC failed and we must provide the
00633      * default failure parameter
00634      */
00635     return self->nolink;
00636   }
00637   Py_BEGIN_ALLOW_THREADS
00638   cpp_res = (double*)self->cpp_dimRpcInfo->getData();
00639   Py_END_ALLOW_THREADS
00640   res = PyFloat_FromDouble(*cpp_res);
00641 
00642   return res; /* res is a new reference and will be owned by the caller */
00643 }
00644 
00645 
00646 static PyObject *
00647 DimRpcInfo_getString (DimRpcInfo_Object * self) {
00648   PyObject *res=NULL;
00649   char * cpp_res=NULL;
00650   int size;
00651 
00652   if (!self->cpp_dimRpcInfo) {
00653     // should never reach this point
00654     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00655     return NULL;
00656   }
00657   /* Making sure we don't block the other Python threads.
00658    * All calls to the DIM API are potentialy blocking!
00659    */
00660   Py_BEGIN_ALLOW_THREADS
00661   size = self->cpp_dimRpcInfo->getSize();
00662   Py_END_ALLOW_THREADS
00663   if (!size) {
00664     /* this means the RPC failed and we must provide the
00665      * default failure parameter
00666      */
00667     return  self->nolink;
00668   }
00669   Py_BEGIN_ALLOW_THREADS
00670   cpp_res = self->cpp_dimRpcInfo->getString();
00671   Py_END_ALLOW_THREADS
00672   res = PyString_FromString(cpp_res);
00673 
00674   return res; /* res is a new reference and will be owned by the caller */
00675 }
00676 
00677 
00678 static PyObject *
00679 DimRpcInfo_getSize (DimRpcInfo_Object * self)  {
00680   /** From the Python point of view, calling this procedure is useless.
00681    * Proving it for the sake of completion
00682    */
00683   PyObject *res=NULL;
00684   int cpp_res=0;
00685 
00686   if (!self->cpp_dimRpcInfo) {
00687     // should never reach this point
00688     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00689     return NULL;
00690   }
00691   /* Making sure we don't block the other Python threads */
00692   Py_BEGIN_ALLOW_THREADS
00693   cpp_res = self->cpp_dimRpcInfo->getSize();
00694   Py_END_ALLOW_THREADS
00695   res = PyInt_FromLong(cpp_res);
00696 
00697   return res; // res is a new reference and will be owned by the caller
00698 }
00699 
00700 
00701 static PyObject *DimRpcInfo_getData(DimRpcInfo_Object * self)   {
00702   PyObject *res=NULL, *tmp=NULL;
00703   char *buff=NULL;
00704   int buff_size=0;
00705 
00706   if (!self->cpp_dimRpcInfo) {
00707     // should never reach this point
00708     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00709     return NULL;
00710   }
00711   /* Making sure we don't block the other Python threads */
00712   Py_BEGIN_ALLOW_THREADS
00713   buff = (char*)self->cpp_dimRpcInfo->getData();
00714   buff_size = self->cpp_dimRpcInfo->getSize();
00715   Py_END_ALLOW_THREADS
00716   if (!buff || !buff_size) {
00717     /* The callback has failed and we provide the error object */
00718     return self->nolink;
00719   }
00720   res = dim_buf_to_tuple(self->format_out, buff, buff_size);
00721   /* In case of a single object tuple, return the object not the tuple */
00722   if (res && PyTuple_Size(res)==1) {
00723     // in case there is only an object
00724     tmp = PyTuple_GetItem(res, 0);
00725     Py_INCREF(tmp);
00726     Py_DECREF(res);
00727     return tmp;
00728   }
00729 
00730   return res; // res is a new reference and will be owned by the caller
00731 }
00732 
00733 
00734 static PyObject *
00735 DimRpcInfo_setData (DimRpcInfo_Object* self, PyObject* args)  {
00736   /** Gets some Python objects and converts them to the appropiate C++ values.
00737    * The conversion is done based on the arguments supplied when the RPC
00738    * command was created.
00739    */
00740   char *buff=NULL;
00741   unsigned int buff_size=0;
00742 
00743   if (!self->cpp_dimRpcInfo) {
00744     /* should never reach this point */
00745     PyErr_SetString(PyExc_AttributeError, "C++ Dim RPC object is NULL");
00746     return NULL;
00747   }
00748 
00749   //printPyObject(args);
00750   if (iterator_to_allocated_buffer(args, self->format_in,
00751            (char **)&buff, &buff_size) ) {
00752     /* The setData() method of DimInfo is blocking. This creates a
00753      * deadlock between the calling thread that holds the python
00754      * global interpretor lock and the DIM global lock
00755      */
00756     Py_BEGIN_ALLOW_THREADS
00757     self->cpp_dimRpcInfo->setData(buff, buff_size);
00758     Py_END_ALLOW_THREADS
00759     delete buff;
00760   } else {
00761     PyErr_SetString(PyExc_AttributeError,
00762         "Could not convert arguments to C buffer");
00763     return NULL;
00764   }
00765 
00766   Py_RETURN_NONE;
00767 }
00768 
00769 
00770 static PyObject *
00771 DimRpcInfo_rpcInfoHandler (DimRpcInfo_Object* /* self */) {
00772   /** Dummy method for the python DimRpcInfo class.
00773    * Not really needed, provided just to make all the DimRpcInfo class
00774    * methods visible in Python
00775    */
00776   //print("RPC call received in C++\n");
00777   Py_RETURN_NONE;
00778 }
00779 
00780 static PyMethodDef DimRpcInfo_methods[] = {
00781   {"name"      , (PyCFunction)DimRpcInfo_name       , METH_NOARGS,
00782    "Returns the name of the service."                        },
00783   {"getData"   , (PyCFunction)DimRpcInfo_getData    , METH_NOARGS,
00784    "Returns the received C complex data as a Python objects"           },
00785   {"getInt"    , (PyCFunction)DimRpcInfo_getInt     , METH_NOARGS,
00786    "Returns the received C integer data as a Python int"           },
00787   {"getDouble" , (PyCFunction)DimRpcInfo_getDouble  , METH_NOARGS,
00788    "Returns the received C double data as a Python float"            },
00789   {"getFloat"  , (PyCFunction)DimRpcInfo_getFloat   , METH_NOARGS,
00790    "Returns the received C float data as a Python float"           },
00791   {"getString" , (PyCFunction)DimRpcInfo_getString  , METH_NOARGS,
00792    "Returns the received C string data as a Python string"         },
00793   {"getSize"   , (PyCFunction)DimRpcInfo_getSize    , METH_NOARGS,
00794    "Returns the total received C data size as a Python int"    },
00795   {"setData"   , (PyCFunction)DimRpcInfo_setData    , METH_VARARGS,
00796    "Sets results data according to the initial format string"},
00797   {"rpcInfoHandler", (PyCFunction)DimRpcInfo_rpcInfoHandler , METH_NOARGS,
00798    "Dummy function for the rpcHandler part"                  },
00799   {NULL, NULL, 0, NULL}  /* Sentinel */
00800 };
00801 
00802 
00803 static PyTypeObject DimRpcInfo_Type = {
00804   PyObject_HEAD_INIT(NULL)
00805   0,                         /*ob_size*/
00806   "dim.DimRpcInfo",          /*tp_name*/
00807   sizeof(DimRpcInfo_Object), /*tp_basicsize*/
00808   0,                         /*tp_itemsize*/
00809   (destructor)DimRpcInfo_dealloc, /*tp_dealloc*/
00810   0,                         /*tp_print*/
00811   0,                         /*tp_getattr*/
00812   0,                         /*tp_setattr*/
00813   0,                         /*tp_compare*/
00814   0,                         /*tp_repr*/
00815   0,                         /*tp_as_number*/
00816   0,                         /*tp_as_sequence*/
00817   0,                         /*tp_as_mapping*/
00818   0,                         /*tp_hash */
00819   0,                         /*tp_call*/
00820   0,                         /*tp_str*/
00821   0,                         /*tp_getattro*/
00822   0,                         /*tp_setattro*/
00823   0,                         /*tp_as_buffer*/
00824   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
00825   "DimRpcInfo object",       /* tp_doc */
00826   0,                         /* tp_traverse */
00827   0,                         /* tp_clear */
00828   0,                         /* tp_richcompare */
00829   0,                         /* tp_weaklistoffset */
00830   0,                         /* tp_iter */
00831   0,                         /* tp_iternext */
00832   DimRpcInfo_methods,        /* tp_methods */
00833   0,                         /* tp_members */
00834   0,                         /* tp_getset */
00835   0,                         /* tp_base */
00836   0,                         /* tp_dict */
00837   0,                         /* tp_descr_get */
00838   0,                         /* tp_descr_set */
00839   0,                         /* tp_dictoffset */
00840   (initproc)DimRpcInfo_init, /* tp_init */ /* init is the same as new */
00841   0,                         /* tp_alloc */
00842   DimRpcInfo_new,            /* tp_new */
00843   _PyObject_Del,              /* tp_free */
00844   0,                          /* tp_is_gc */
00845   0,                          /* tp_bases */
00846   0,                          /* tp_mro */
00847   0,                          /* tp_cache */
00848   0,                          /* tp_subclasses */
00849   0,                          /* tp_weaklist */
00850   (destructor)DimRpcInfo_dealloc  /* tp_del */
00851 };
00852 
00853 /**@}
00854  */
00855 #ifndef PyMODINIT_FUNC  /* declarations for DLL import/export */
00856 #define PyMODINIT_FUNC void
00857 #endif
00858 
00859 PyMODINIT_FUNC initdimcpp(void)  {
00860   PyObject *m;
00861 
00862   /* This is needed if the program is threaded.
00863    * Creates the global interpretor lock
00864    */
00865   PyEval_InitThreads();
00866   /* Initializing Python classes.
00867    * Basically this functions will make the necessary initializations
00868    * to the _Type objects.
00869    */
00870   debug("Initializing C++ DIM interface...  \n");
00871   if (PyType_Ready(&DimRpc_Type) < 0) {
00872     print("Could not initialize type DimRpc\n");
00873     return;
00874   }
00875   if (PyType_Ready(&DimRpcInfo_Type) < 0) {
00876     printf("Could not initialize type DimRpcInfo\n");
00877     return;
00878   }
00879   /* Initializing Python module */
00880   m = Py_InitModule3("dimcpp", dimcpp_methods, "DIM C++ methods");
00881   PyEval_InitThreads();
00882   if (m == NULL) {
00883     print("Could not initialise dimcpp module\n");
00884     return;
00885   }
00886   /* Making sure that the new class objects will not by cleaned out by the
00887    * garbage collector
00888    */
00889   Py_INCREF(&DimRpc_Type);
00890   Py_INCREF(&DimRpcInfo_Type);
00891   /* Adding the objects to the created module */
00892   PyModule_AddObject(m, "DimRpc", (PyObject *)&DimRpc_Type);
00893   PyModule_AddObject(m, "DimRpcInfo", (PyObject *)&DimRpcInfo_Type);
00894   /* Magic call to DIM API. Makes sure all the data type sizes are respected.*/
00895   dic_disable_padding();
00896 }
00897 

Generated on 5 Feb 2014 for PyDIM by  doxygen 1.4.7