Panda3D
pythonCallbackObject.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pythonCallbackObject.cxx
10  * @author drose
11  * @date 2009-03-13
12  */
13 
14 #include "pythonCallbackObject.h"
15 
16 #ifdef HAVE_PYTHON
17 
18 #include "py_panda.h"
19 #include "pythonThread.h"
20 #include "callbackData.h"
21 #include "config_putil.h"
22 
23 TypeHandle PythonCallbackObject::_type_handle;
24 
25 Configure(config_pythonCallbackObject);
26 ConfigureFn(config_pythonCallbackObject) {
27  PythonCallbackObject::init_type();
28 }
29 
30 #ifndef CPPPARSER
31 extern struct Dtool_PyTypedObject Dtool_TypedObject;
32 #endif
33 
34 /**
35  *
36  */
37 PythonCallbackObject::
38 PythonCallbackObject(PyObject *function) {
39  _function = Py_None;
40  Py_INCREF(_function);
41 
42  set_function(function);
43 
44 #ifndef SIMPLE_THREADS
45  // Ensure that the Python threading system is initialized and ready to go.
46 #ifdef WITH_THREAD // This symbol defined within Python.h
47 
48 #if PY_VERSION_HEX >= 0x03020000
49  Py_Initialize();
50 #endif
51 
52  PyEval_InitThreads();
53 #endif
54 #endif
55 }
56 
57 /**
58  *
59  */
60 PythonCallbackObject::
61 ~PythonCallbackObject() {
62  Py_DECREF(_function);
63 }
64 
65 /**
66  * Replaces the function that is called for the callback. runs. The
67  * parameter should be a Python callable object.
68  */
69 void PythonCallbackObject::
70 set_function(PyObject *function) {
71  Py_DECREF(_function);
72  _function = function;
73  Py_INCREF(_function);
74  if (_function != Py_None && !PyCallable_Check(_function)) {
75  nassert_raise("Invalid function passed to PythonCallbackObject");
76  }
77 }
78 
79 /**
80  * Returns the function that is called for the callback.
81  */
82 PyObject *PythonCallbackObject::
83 get_function() {
84  Py_INCREF(_function);
85  return _function;
86 }
87 
88 /**
89  * This method called when the callback is triggered; it *replaces* the
90  * original function. To continue performing the original function, you must
91  * call cbdata->upcall() during the callback.
92  */
93 void PythonCallbackObject::
94 do_callback(CallbackData *cbdata) {
95 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
96  // Use PyGILState to protect this asynchronous call.
97  PyGILState_STATE gstate;
98  gstate = PyGILState_Ensure();
99 #endif
100 
101  do_python_callback(cbdata);
102 
103 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
104  PyGILState_Release(gstate);
105 #endif
106 }
107 
108 /**
109  * The Python calls that implement do_callback(). This function is separate
110  * so we can acquire the Python interpretor lock while it runs.
111  */
112 void PythonCallbackObject::
113 do_python_callback(CallbackData *cbdata) {
114  nassertv(cbdata != nullptr);
115 
116  // Wrap the cbdata up in a Python object, then put it in a tuple, for the
117  // argument list.
118  PyObject *pycbdata =
119  DTool_CreatePyInstanceTyped(cbdata, Dtool_TypedObject,
120  false, false, cbdata->get_type_index());
121  PyObject *args = Py_BuildValue("(O)", pycbdata);
122  Py_DECREF(pycbdata);
123 
124  PyObject *result = PythonThread::call_python_func(_function, args);
125  Py_DECREF(args);
126 
127  if (result == nullptr) {
128  if (PyErr_Occurred() != PyExc_SystemExit) {
129  util_cat.error()
130  << "Exception occurred in " << *this << "\n";
131  }
132  } else {
133  Py_DECREF(result);
134  }
135 }
136 
137 #endif // HAVE_PYTHON
This is a generic data block that is passed along to a CallbackObject when a callback is made.
Definition: callbackData.h:29
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
int get_type_index() const
Returns the internal index number associated with this object's TypeHandle, a unique number for each ...
Definition: typedObject.I:20