Panda3D
Loading...
Searching...
No Matches
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
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
23TypeHandle PythonCallbackObject::_type_handle;
24
25Configure(config_pythonCallbackObject);
26ConfigureFn(config_pythonCallbackObject) {
27 PythonCallbackObject::init_type();
28}
29
30#ifndef CPPPARSER
31extern struct Dtool_PyTypedObject Dtool_TypedObject;
32#endif
33
34/**
35 *
36 */
37PythonCallbackObject::
38PythonCallbackObject(PyObject *function) {
39 _function = Py_None;
40 Py_INCREF(_function);
41
42 set_function(function);
43
44#if !defined(SIMPLE_THREADS) && defined(WITH_THREAD)
45 // Ensure that the Python threading system is initialized and ready to go.
46
47#if PY_VERSION_HEX >= 0x03020000
48 Py_Initialize();
49#endif
50
51#if PY_VERSION_HEX < 0x03090000
52 // PyEval_InitThreads is now a deprecated no-op in Python 3.9+
53 PyEval_InitThreads();
54#endif // PY_VERSION_HEX
55#endif // WITH_THREAD
56}
57
58/**
59 *
60 */
61PythonCallbackObject::
62~PythonCallbackObject() {
63 // This may be called from the cull or draw thread, so we have to be sure we
64 // own the GIL.
65#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
66 PyGILState_STATE gstate;
67 gstate = PyGILState_Ensure();
68#endif
69
70 Py_DECREF(_function);
71
72#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
73 PyGILState_Release(gstate);
74#endif
75}
76
77/**
78 * Replaces the function that is called for the callback. runs. The
79 * parameter should be a Python callable object.
80 */
81void PythonCallbackObject::
82set_function(PyObject *function) {
83 Py_DECREF(_function);
84 _function = function;
85 Py_INCREF(_function);
86 if (_function != Py_None && !PyCallable_Check(_function)) {
87 nassert_raise("Invalid function passed to PythonCallbackObject");
88 }
89}
90
91/**
92 * Returns the function that is called for the callback.
93 */
94PyObject *PythonCallbackObject::
95get_function() {
96 Py_INCREF(_function);
97 return _function;
98}
99
100/**
101 * This method called when the callback is triggered; it *replaces* the
102 * original function. To continue performing the original function, you must
103 * call cbdata->upcall() during the callback.
104 */
105void PythonCallbackObject::
106do_callback(CallbackData *cbdata) {
107#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
108 // Use PyGILState to protect this asynchronous call.
109 PyGILState_STATE gstate;
110 gstate = PyGILState_Ensure();
111#endif
112
113 do_python_callback(cbdata);
114
115#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
116 PyGILState_Release(gstate);
117#endif
118}
119
120/**
121 * The Python calls that implement do_callback(). This function is separate
122 * so we can acquire the Python interpretor lock while it runs.
123 */
124void PythonCallbackObject::
125do_python_callback(CallbackData *cbdata) {
126 nassertv(cbdata != nullptr);
127
128 // Wrap the cbdata up in a Python object, then put it in a tuple, for the
129 // argument list.
130 PyObject *pycbdata =
131 DTool_CreatePyInstanceTyped(cbdata, Dtool_TypedObject,
132 false, false, cbdata->get_type_index());
133 PyObject *args = Py_BuildValue("(O)", pycbdata);
134 Py_DECREF(pycbdata);
135
136 PyObject *result = PythonThread::call_python_func(_function, args);
137 Py_DECREF(args);
138
139 if (result == nullptr) {
140 if (PyErr_Occurred() != PyExc_SystemExit) {
141 util_cat.error()
142 << "Exception occurred in " << *this << "\n";
143 }
144 } else {
145 Py_DECREF(result);
146 }
147}
148
149#endif // HAVE_PYTHON
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a generic data block that is passed along to a CallbackObject when a callback is made.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.