pythonutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2007-2012 by Johan De Taeye, frePPLe bvba *
4  * *
5  * This library is free software; you can redistribute it and/or modify it *
6  * under the terms of the GNU Affero General Public License as published *
7  * by the Free Software Foundation; either version 3 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This library is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU Affero General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU Affero General Public *
16  * License along with this program. *
17  * If not, see <http://www.gnu.org/licenses/>. *
18  * *
19  ***************************************************************************/
20 
21 /** @file pythonutils.cpp
22  * @brief Reusable functions for python functionality.
23  *
24  * The structure of the C++ wrappers around the C Python API is heavily
25  * inspired on the design of PyCXX.<br>
26  * More information can be found on http://cxx.sourceforge.net
27  */
28 
29 #define FREPPLE_CORE
30 #include "frepple/utils.h"
31 
32 namespace frepple
33 {
34 namespace utils
35 {
36 
40 
41 DECLARE_EXPORT PyObject *PythonInterpreter::module = NULL;
42 DECLARE_EXPORT string PythonInterpreter::encoding;
43 DECLARE_EXPORT PyThreadState* PythonInterpreter::mainThreadState = NULL;
44 
45 
47 {
48  return encoding.c_str();
49 }
50 
51 
52 DECLARE_EXPORT void PythonInterpreter::initialize(int argc, char *argv[])
53 {
54  // Initialize the Python interpreter in case we are embedding it in frePPLe.
55  if(!Py_IsInitialized())
56  {
57  Py_InitializeEx(0); // The arg 0 indicates that the interpreter doesn't
58  // implement its own signal handler
59  // Pass the command line arguments to Python as well
60 #if PY_VERSION_HEX > 0x02060600
61  if (argc>0) PySys_SetArgvEx(argc, argv, 0);
62 #endif
63  // Initializes threads
64  PyEval_InitThreads();
65  mainThreadState = PyEval_SaveThread();
66  }
67 
68  // Capture global lock
69  PyGILState_STATE state = PyGILState_Ensure();
70 
71  // Create the frePPLe module
72  module = Py_InitModule3("frepple", NULL, "Access to the frePPLe library");
73  if (!module)
74  {
75  PyGILState_Release(state);
76  throw RuntimeException("Can't initialize Python interpreter");
77  }
78 
79  // Make the datetime types available
80  PyDateTime_IMPORT;
81 
82  // Create python exception types
83  int nok = 0;
84  PythonLogicException = PyErr_NewException((char*)"frepple.LogicException", NULL, NULL);
85  Py_IncRef(PythonLogicException);
86  nok += PyModule_AddObject(module, "LogicException", PythonLogicException);
87  PythonDataException = PyErr_NewException((char*)"frepple.DataException", NULL, NULL);
88  Py_IncRef(PythonDataException);
89  nok += PyModule_AddObject(module, "DataException", PythonDataException);
90  PythonRuntimeException = PyErr_NewException((char*)"frepple.RuntimeException", NULL, NULL);
91  Py_IncRef(PythonRuntimeException);
92  nok += PyModule_AddObject(module, "RuntimeException", PythonRuntimeException);
93 
94  // Add a string constant for the version
95  nok += PyModule_AddStringConstant(module, "version", PACKAGE_VERSION);
96 
97  // Redirect the stderr and stdout streams of Python
98  registerGlobalMethod("log", python_log, METH_VARARGS,
99  "Prints a string to the frePPLe log file.", false);
100  PyRun_SimpleString(
101  "import frepple, sys\n"
102  "class redirect:\n"
103  "\tdef write(self,str):\n"
104  "\t\tfrepple.log(str)\n"
105  "sys.stdout = redirect()\n"
106  "sys.stderr = redirect()"
107  );
108 
109  // Get the preferred Python locale
110  PyObject* localemodule = PyImport_ImportModule("locale");
111  if (!localemodule)
112  {
113  PyGILState_Release(state);
114  throw RuntimeException("Can't import 'locale' Python module");
115  }
116  else
117  {
118  PyObject* moduledict = PyModule_GetDict(localemodule);
119  PyObject* func = PyDict_GetItemString(moduledict, "getpreferredencoding");
120  if (!func)
121  {
122  PyGILState_Release(state);
123  throw RuntimeException("Can't find 'getpreferredencoding' Python function");
124  }
125  PyObject* retval = PyEval_CallObject(func, NULL);
126  if (retval)
127  {
128  encoding = PyString_AsString(retval);
129  Py_XDECREF(retval);
130  }
131  Py_XDECREF(localemodule);
132  }
133 
134  // Release the lock
135  PyGILState_Release(state);
136 
137  // A final check...
138  if (nok) throw RuntimeException("Can't initialize Python interpreter");
139 }
140 
141 
143 {
144  // Only valid if this is an embedded interpreter
145  if (!mainThreadState) return;
146 
147  // Swap to the main thread and exit
148  PyEval_AcquireLock();
149  PyEval_RestoreThread(mainThreadState);
150  Py_Finalize();
151 }
152 
153 
155 {
156  // Check whether the thread already has a Python state
157  PyThreadState * myThreadState = PyGILState_GetThisThreadState();
158  if (myThreadState) return;
159 
160  // Create a new state
161  PyThreadState *tcur = PyThreadState_New(PyInterpreterState_Head());
162  if (!tcur) throw RuntimeException("Can't create new thread state");
163 
164  // Make the new state current
165  PyEval_RestoreThread(tcur);
166  PyEval_ReleaseLock();
167 }
168 
169 
171 {
172  // Check whether the thread already has a Python state
173  PyThreadState * tcur = PyGILState_GetThisThreadState();
174  if (!tcur) return;
175 
176  // Delete the current Python thread state
177  PyEval_RestoreThread(tcur);
178  PyThreadState_Clear(tcur);
179  PyThreadState_DeleteCurrent(); // This releases the GIL too!
180 }
181 
182 
184 {
185  // Capture global lock
186  PyGILState_STATE state = PyGILState_Ensure();
187 
188  // Execute the command
189  PyObject *m = PyImport_AddModule("__main__");
190  if (!m)
191  {
192  // Release the global Python lock
193  PyGILState_Release(state);
194  throw RuntimeException("Can't initialize Python interpreter");
195  }
196  PyObject *d = PyModule_GetDict(m);
197  if (!d)
198  {
199  // Release the global Python lock
200  PyGILState_Release(state);
201  throw RuntimeException("Can't initialize Python interpreter");
202  }
203 
204  // Execute the Python code. Note that during the call the Python lock can be
205  // temporarily released.
206  PyObject *v = PyRun_String(cmd, Py_file_input, d, d);
207  if (!v)
208  {
209  // Print the error message
210  PyErr_Print();
211  // Release the global Python lock
212  PyGILState_Release(state);
213  throw RuntimeException("Error executing Python command");
214  }
215  Py_DECREF(v);
216  if (Py_FlushLine()) PyErr_Clear();
217 
218  // Release the global Python lock
219  PyGILState_Release(state);
220 }
221 
222 
224 {
225  // A file to be executed.
226  // We build an equivalent python command rather than using the
227  // PyRun_File function. On windows different versions of the
228  // VC compiler have a different structure for FILE, thus making it
229  // impossible to use a lib compiled in python version x when compiling
230  // under version y. Quite ugly... :-( :-( :-(
231  for (string::size_type pos = filename.find_first_of("'", 0);
232  pos < string::npos;
233  pos = filename.find_first_of("'", pos))
234  {
235  filename.replace(pos,1,"\\'",2); // Replacing ' with \'
236  pos+=2;
237  }
238  string cmd = "execfile(ur'" + filename + "')\n";
239  execute(cmd.c_str());
240 }
241 
242 
244  const char* name, PyCFunction method, int flags, const char* doc, bool lock
245 )
246 {
247  // Define a new method object.
248  // We need are leaking the memory allocated for it to assure the data
249  // are available at all times to Python.
250  string *leakingName = new string(name);
251  string *leakingDoc = new string(doc);
252  PyMethodDef *newMethod = new PyMethodDef;
253  newMethod->ml_name = leakingName->c_str();
254  newMethod->ml_meth = method;
255  newMethod->ml_flags = flags;
256  newMethod->ml_doc = leakingDoc->c_str();
257 
258  // Lock the interpreter
259  PyGILState_STATE state;
260  if (lock) state = PyGILState_Ensure();
261 
262  // Register a new C function in Python
263  PyObject* mod = PyString_FromString("frepple");
264  if (!mod)
265  {
266  if (lock) PyGILState_Release(state);;
267  throw RuntimeException("Error registering a new Python method");
268  }
269  PyObject* func = PyCFunction_NewEx(newMethod, NULL, mod);
270  Py_DECREF(mod);
271  if (!func)
272  {
273  if (lock) PyGILState_Release(state);
274  throw RuntimeException("Error registering a new Python method");
275  }
276 
277  // Add the method to the module dictionary
278  PyObject* moduledict = PyModule_GetDict(module);
279  if (!moduledict)
280  {
281  Py_DECREF(func);
282  if (lock) PyGILState_Release(state);
283  throw RuntimeException("Error registering a new Python method");
284  }
285  if (PyDict_SetItemString(moduledict ,leakingName->c_str(), func) < 0)
286  {
287  Py_DECREF(func);
288  if (lock) PyGILState_Release(state);
289  throw RuntimeException("Error registering a new Python method");
290  }
291  Py_DECREF(func);
292 
293  // Release the interpeter
294  if (lock) PyGILState_Release(state);
295 }
296 
297 
299 (const char* c, PyCFunctionWithKeywords f, int i, const char* d, bool b)
300 {
301  registerGlobalMethod(c, reinterpret_cast<PyCFunction>(f), i | METH_KEYWORDS, d, b);
302 }
303 
304 
305 PyObject* PythonInterpreter::python_log(PyObject *self, PyObject *args)
306 {
307  // Pick up arguments
308  char *data;
309  int ok = PyArg_ParseTuple(args, "s:log", &data);
310  if (!ok) return NULL;
311 
312  // Print and flush the output stream
313  logger << data;
314  logger.flush();
315 
316  // Return code
317  return Py_BuildValue(""); // Safer than using Py_None, which is not
318  // portable across compilers
319 }
320 
321 
322 const PyTypeObject PythonType::PyTypeObjectTemplate =
323 {
324  PyObject_HEAD_INIT(NULL)
325  0, /* ob_size */
326  "frepple.unspecified", /* WILL BE UPDATED tp_name */
327  0, /* WILL BE UPDATED tp_basicsize */
328  0, /* tp_itemsize */
329  0, /* CAN BE UPDATED tp_dealloc */
330  0, /* tp_print */
331  0, /* tp_getattr */
332  0, /* tp_setattr */
333  0, /* CAN BE UPDATED tp_compare */
334  0, /* tp_repr */
335  0, /* tp_as_number */
336  0, /* tp_as_sequence */
337  0, /* tp_as_mapping */
338  reinterpret_cast<hashfunc>(_Py_HashPointer), /* tp_hash */
339  0, /* CAN BE UPDATED tp_call */
340  0, /* CAN BE UPDATED tp_str */
341  0, /* CAN BE UPDATED tp_getattro */
342  0, /* CAN BE UPDATED tp_setattro */
343  0, /* tp_as_buffer */
344  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
345  "std doc", /* CAN BE UPDATED tp_doc */
346  0, /* tp_traverse */
347  0, /* tp_clear */
348  0, /* tp_richcompare */
349  0, /* tp_weaklistoffset */
350  0, /* CAN BE UPDATED tp_iter */
351  0, /* CAN BE UPDATED tp_iternext */
352  0, /* tp_methods */
353  0, /* tp_members */
354  0, /* tp_getset */
355  0, /* tp_base */
356  0, /* tp_dict */
357  0, /* tp_descr_get */
358  0, /* tp_descr_set */
359  0, /* tp_dictoffset */
360  0, /* tp_init */
361  0, /* tp_alloc */
362  0, /* CAN BE UPDATED tp_new */
363  0, /* tp_free */
364 };
365 
366 
368 {
369  PyDateTime_IMPORT;
370  // The standard library function localtime() is not re-entrant: the same
371  // static structure is used for all calls. In a multi-threaded environment
372  // the function is not to be used.
373  // The POSIX standard defines a re-entrant version of the function:
374  // localtime_r.
375  // Visual C++ 6.0 and Borland 5.5 are missing it, but provide a thread-safe
376  // variant without changing the function semantics.
377  time_t ticks = d.getTicks();
378 #ifdef HAVE_LOCALTIME_R
379  struct tm t;
380  localtime_r(&ticks, &t);
381 #else
382  struct tm t = *localtime(&ticks);
383 #endif
384  obj = PyDateTime_FromDateAndTime(t.tm_year+1900, t.tm_mon+1, t.tm_mday,
385  t.tm_hour, t.tm_min, t.tm_sec, 0);
386 }
387 
388 
390 {
391  PyDateTime_IMPORT;
392  if (PyDateTime_Check(obj))
393  return Date(
394  PyDateTime_GET_YEAR(obj),
395  PyDateTime_GET_MONTH(obj),
396  PyDateTime_GET_DAY(obj),
397  PyDateTime_DATE_GET_HOUR(obj),
398  PyDateTime_DATE_GET_MINUTE(obj),
399  PyDateTime_DATE_GET_SECOND(obj)
400  );
401  else if (PyDate_Check(obj))
402  return Date(
403  PyDateTime_GET_YEAR(obj),
404  PyDateTime_GET_MONTH(obj),
405  PyDateTime_GET_DAY(obj)
406  );
407  else if (PyString_Check(obj))
408  {
409  if (PyUnicode_Check(obj))
410  {
411  // Replace the unicode object with a string encoded in the correct locale
412  const_cast<PyObject*&>(obj) =
413  PyUnicode_AsEncodedString(obj, PythonInterpreter::getPythonEncoding(), "ignore");
414  }
415  return Date(PyString_AsString(PyObject_Str(obj)));
416  }
417  else
418  throw DataException(
419  "Invalid data type. Expecting datetime.date, datetime.datetime or string"
420  );
421 }
422 
423 
425 {
426  obj = p ? static_cast<PyObject*>(p) : Py_None;
427  Py_INCREF(obj);
428 }
429 
430 
431 DECLARE_EXPORT PythonType::PythonType(size_t base_size, const type_info* tp)
432  : cppClass(tp)
433 {
434  // Allocate a new type object if it doesn't exist yet.
435  // We copy from a template type definition.
436  table = new PyTypeObject(PyTypeObjectTemplate);
437  table->tp_basicsize = base_size;
438 }
439 
440 
442 {
443  // Scan the types already registered
444  for (vector<PythonType*>::const_iterator i = table.begin(); i != table.end(); ++i)
445  if (**i==*t) return *i;
446 
447  // Not found in the vector, so create a new one
448  PythonType *cachedTypePtr = new PythonType(size, t);
449  table.push_back(cachedTypePtr);
450  return cachedTypePtr;
451 }
452 
453 
454 DECLARE_EXPORT PyObject* Object::toXML(PyObject* self, PyObject* args)
455 {
456  try
457  {
458  // Parse the argument
459  PyObject *filearg = NULL;
460  char mode = 'S';
461  if (!PyArg_ParseTuple(args, "|cO:toXML", &mode, &filearg))
462  return NULL;
463 
464  // Create the XML string.
465  ostringstream ch;
466  XMLOutput x(ch);
467  x.setReferencesOnly(true);
468  if (mode == 'S')
470  else if (mode == 'P')
472  else if (mode == 'D')
474  else
475  throw DataException("Invalid output mode");
476 
477  // The next call assumes the self argument is an instance of the Object
478  // base class. We don't need to check this explicitly since we expose
479  // this method only on subclasses.
480  static_cast<Object*>(self)->writeElement
481  (&x, *(static_cast<Object*>(self)->getType().category->typetag));
482  // Write the output...
483  if (filearg)
484  {
485  if (PyFile_Check(filearg))
486  {
487  // ... to a file
488  return PyFile_WriteString(ch.str().c_str(), filearg) ?
489  NULL : // Error writing to the file
490  Py_BuildValue("");
491  }
492  else
493  // The argument is not a file
494  throw LogicException("Expecting a file argument");
495  }
496  else
497  // ... to a string
498  return PythonObject(ch.str());
499  }
500  catch(...)
501  {
503  return NULL;
504  }
505  throw LogicException("Unreachable code reached");
506 }
507 
508 
510 (const char* method_name, PyCFunction f, int flags, const char* doc )
511 {
512  unsigned short i = 0;
513 
514  // Create a method table array
515  if (!table->tp_methods)
516  // Allocate a first block
517  table->tp_methods = new PyMethodDef[methodArraySize];
518  else
519  {
520  // Find the first non-empty method record
521  while (table->tp_methods[i].ml_name) i++;
522  if (i % methodArraySize == methodArraySize - 1)
523  {
524  // Allocation of a bigger buffer is required
525  PyMethodDef* tmp = new PyMethodDef[i + 1 + methodArraySize];
526  for(unsigned short j = 0; j < i; j++)
527  tmp[j] = table->tp_methods[j];
528  delete [] table->tp_methods;
529  table->tp_methods = tmp;
530  }
531  }
532 
533  // Populate a method definition struct
534  table->tp_methods[i].ml_name = method_name;
535  table->tp_methods[i].ml_meth = f;
536  table->tp_methods[i].ml_flags = flags;
537  table->tp_methods[i].ml_doc = doc;
538 
539  // Append an empty terminator record
540  table->tp_methods[++i].ml_name = NULL;
541  table->tp_methods[i].ml_meth = NULL;
542  table->tp_methods[i].ml_flags = 0;
543  table->tp_methods[i].ml_doc = NULL;
544 }
545 
546 
548 (const char* c, PyCFunctionWithKeywords f, int i, const char* d)
549 {
550  addMethod(c, reinterpret_cast<PyCFunction>(f), i | METH_KEYWORDS, d);
551 }
552 
553 
555 {
556  // Register the new type in the module
557  PyGILState_STATE state = PyGILState_Ensure();
558  if (PyType_Ready(table) < 0)
559  {
560  PyGILState_Release(state);
561  throw RuntimeException(string("Can't register python type ") + table->tp_name);
562  }
563  Py_INCREF(table);
564  int result = PyModule_AddObject(
566  table->tp_name + 8, // Note: +8 is to skip the "frepple." characters in the name
567  reinterpret_cast<PyObject*>(table)
568  );
569  PyGILState_Release(state);
570  return result;
571 }
572 
573 
575 {
576  // Rethrowing the exception to catch its type better
577  try {throw;}
578  catch (const DataException& e)
579  {PyErr_SetString(PythonDataException, e.what());}
580  catch (const LogicException& e)
581  {PyErr_SetString(PythonLogicException, e.what());}
582  catch (const RuntimeException& e)
583  {PyErr_SetString(PythonRuntimeException, e.what());}
584  catch (const exception& e)
585  {PyErr_SetString(PyExc_Exception, e.what());}
586  catch (...)
587  {PyErr_SetString(PyExc_Exception, "Unidentified exception");}
588 }
589 
590 
592 {
593  if (n.empty())
594  {
595  // Resetting to NULL when the string is empty
596  func = NULL;
597  return;
598  }
599 
600  // Find the Python function
601  PyGILState_STATE pythonstate = PyGILState_Ensure();
602  func = PyRun_String(n.c_str(), Py_eval_input,
603  PyEval_GetGlobals(), PyEval_GetLocals() );
604  if (!func)
605  {
606  PyGILState_Release(pythonstate);
607  throw DataException("Python function '" + n + "' not defined");
608  }
609  if (!PyCallable_Check(func))
610  {
611  PyGILState_Release(pythonstate);
612  throw DataException("Python object '" + n + "' is not a function");
613  }
614  Py_INCREF(func);
615 
616  // Store the Python function
617  PyGILState_Release(pythonstate);
618 }
619 
620 
622 {
623  if (!p || p == Py_None)
624  {
625  // Resetting to null
626  func = NULL;
627  return;
628  }
629 
630  if (!PyCallable_Check(p))
631  {
632  // It's not a callable object. Interprete it as a function name and
633  // look it up.
634  PyGILState_STATE pythonstate = PyGILState_Ensure();
635  string n = PythonObject(p).getString();
636  p = PyRun_String(n.c_str(), Py_eval_input,
637  PyEval_GetGlobals(), PyEval_GetLocals() );
638  if (!p)
639  {
640  PyGILState_Release(pythonstate);
641  throw DataException("Python function '" + n + "' not defined");
642  }
643  if (!PyCallable_Check(p))
644  {
645  PyGILState_Release(pythonstate);
646  throw DataException("Python object '" + n + "' is not a function");
647  }
648  PyGILState_Release(pythonstate);
649  }
650 
651  // Store the Python function
652  func = p;
653  Py_INCREF(func);
654 }
655 
656 
658 {
659  if (!func) return PythonObject();
660  PyGILState_STATE pythonstate = PyGILState_Ensure();
661  PyObject* result = PyEval_CallFunction(func, "()");
662  if (!result)
663  {
664  logger << "Error: Exception caught when calling Python function '"
665  << (func ? PyEval_GetFuncName(func) : "NULL") << "'" << endl;
666  if (PyErr_Occurred()) PyErr_PrintEx(0);
667  }
668  PyGILState_Release(pythonstate);
669  return PythonObject(result);
670 }
671 
672 
674 {
675  if (!func) return PythonObject();
676  PyGILState_STATE pythonstate = PyGILState_Ensure();
677  PyObject* result = PyEval_CallFunction(func, "(O)", p);
678  if (!result)
679  {
680  logger << "Error: Exception caught when calling Python function '"
681  << (func ? PyEval_GetFuncName(func) : "NULL") << "'" << endl;
682  if (PyErr_Occurred()) PyErr_PrintEx(0);
683  }
684  PyGILState_Release(pythonstate);
685  return PythonObject(result);
686 }
687 
688 
689 DECLARE_EXPORT PythonObject PythonFunction::call(const PyObject* p, const PyObject* q) const
690 {
691  if (!func) return PythonObject();
692  PyGILState_STATE pythonstate = PyGILState_Ensure();
693  PyObject* result = PyEval_CallFunction(func, "(OO)", p, q);
694  if (!result)
695  {
696  logger << "Error: Exception caught when calling Python function '"
697  << (func ? PyEval_GetFuncName(func) : "NULL") << "'" << endl;
698  if (PyErr_Occurred()) PyErr_PrintEx(0);
699  }
700  PyGILState_Release(pythonstate);
701  return PythonObject(result);
702 }
703 
704 
705 extern "C" DECLARE_EXPORT PyObject* getattro_handler(PyObject *self, PyObject *name)
706 {
707  try
708  {
709  if (!PyString_Check(name))
710  {
711  PyErr_Format(PyExc_TypeError,
712  "attribute name must be string, not '%s'",
713  name->ob_type->tp_name);
714  return NULL;
715  }
716  PyObject* result = static_cast<PythonExtensionBase*>(self)->getattro(Attribute(PyString_AsString(name)));
717  // Exit 1: Normal
718  if (result) return result;
719  // Exit 2: Exception occurred
720  if (PyErr_Occurred()) return NULL;
721  // Exit 3: No error occurred but the attribute was not found.
722  // Use the standard generic function to pick up standard attributes
723  // (such as __class__, __doc__, ...)
724  // Note that this function also picks up attributes from base classes, but
725  // we can't rely on that: any C++ exceptions are lost along the way...
726  return PyObject_GenericGetAttr(self,name);
727  }
728  catch (...)
729  {
731  return NULL;
732  }
733 }
734 
735 
736 extern "C" DECLARE_EXPORT int setattro_handler(PyObject *self, PyObject *name, PyObject *value)
737 {
738  try
739  {
740  // Pick up the field name
741  if (!PyString_Check(name))
742  {
743  PyErr_Format(PyExc_TypeError,
744  "attribute name must be string, not '%s'",
745  name->ob_type->tp_name);
746  return -1;
747  }
748  PythonObject field(value);
749 
750  // Call the object to update the attribute
751  int result = static_cast<PythonExtensionBase*>(self)->setattro(Attribute(PyString_AsString(name)), field);
752 
753  // Process 'OK' result
754  if (!result) return 0;
755 
756  // Process 'not OK' result - set python error string if it isn't set yet
757  if (!PyErr_Occurred())
758  PyErr_Format(PyExc_AttributeError,
759  "attribute '%s' on '%s' can't be updated",
760  PyString_AsString(name), self->ob_type->tp_name);
761  return -1;
762  }
763  catch (...)
764  {
766  return -1;
767  }
768 }
769 
770 
771 extern "C" DECLARE_EXPORT int compare_handler(PyObject *self, PyObject *other)
772 {
773  try
774  {
775  return static_cast<PythonExtensionBase*>(self)->compare(other);
776  }
777  catch (...)
778  {
780  return -1;
781  }
782 }
783 
784 
785 extern "C" DECLARE_EXPORT PyObject* iternext_handler(PyObject *self)
786 {
787  try
788  {
789  return static_cast<PythonExtensionBase*>(self)->iternext();
790  }
791  catch (...)
792  {
794  return NULL;
795  }
796 }
797 
798 
799 extern "C" DECLARE_EXPORT PyObject* call_handler(PyObject* self, PyObject* args, PyObject* kwds)
800 {
801  try
802  {
803  return static_cast<PythonExtensionBase*>(self)->call(args, kwds);
804  }
805  catch (...)
806  {
808  return NULL;
809  }
810 }
811 
812 
813 extern "C" DECLARE_EXPORT PyObject* str_handler(PyObject* self)
814 {
815  try
816  {
817  return static_cast<PythonExtensionBase*>(self)->str();
818  }
819  catch (...)
820  {
822  return NULL;
823  }
824 }
825 
826 } // end namespace
827 } // end namespace