142 lines
4.5 KiB
C++
142 lines
4.5 KiB
C++
// Filename: pythonCallbackObject.cxx
|
|
// Created by: drose (13Mar09)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
//
|
|
// All use of this software is subject to the terms of the revised BSD
|
|
// license. You should have received a copy of this license along
|
|
// with this source code in a file named "LICENSE."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pythonCallbackObject.h"
|
|
|
|
#ifdef HAVE_PYTHON
|
|
#include "py_panda.h"
|
|
#include "thread.h"
|
|
#include "callbackData.h"
|
|
|
|
TypeHandle PythonCallbackObject::_type_handle;
|
|
|
|
#ifndef CPPPARSER
|
|
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TypedObject;
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PythonCallbackObject::Constructor
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
PythonCallbackObject::
|
|
PythonCallbackObject(PyObject *function) {
|
|
_function = Py_None;
|
|
Py_INCREF(_function);
|
|
|
|
set_function(function);
|
|
|
|
#ifndef SIMPLE_THREADS
|
|
// Ensure that the Python threading system is initialized and ready
|
|
// to go.
|
|
#ifdef WITH_THREAD // This symbol defined within Python.h
|
|
PyEval_InitThreads();
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PythonCallbackObject::Destructor
|
|
// Access: Published, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
PythonCallbackObject::
|
|
~PythonCallbackObject() {
|
|
Py_DECREF(_function);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PythonCallbackObject::set_function
|
|
// Access: Published
|
|
// Description: Replaces the function that is called for the callback.
|
|
// runs. The parameter should be a Python callable
|
|
// object.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PythonCallbackObject::
|
|
set_function(PyObject *function) {
|
|
Py_DECREF(_function);
|
|
_function = function;
|
|
Py_INCREF(_function);
|
|
if (_function != Py_None && !PyCallable_Check(_function)) {
|
|
nassert_raise("Invalid function passed to PythonCallbackObject");
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PythonCallbackObject::get_function
|
|
// Access: Published
|
|
// Description: Returns the function that is called for the callback.
|
|
////////////////////////////////////////////////////////////////////
|
|
PyObject *PythonCallbackObject::
|
|
get_function() {
|
|
Py_INCREF(_function);
|
|
return _function;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PythonCallbackObject::do_callback
|
|
// Access: Public, Virtual
|
|
// Description: This method called when the callback is triggered; it
|
|
// *replaces* the original function. To continue
|
|
// performing the original function, you must call
|
|
// cbdata->upcall() during the callback.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PythonCallbackObject::
|
|
do_callback(CallbackData *cbdata) {
|
|
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
|
// Use PyGILState to protect this asynchronous call.
|
|
PyGILState_STATE gstate;
|
|
gstate = PyGILState_Ensure();
|
|
#endif
|
|
|
|
do_python_callback(cbdata);
|
|
|
|
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
|
PyGILState_Release(gstate);
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PythonCallbackObject::do_python_callback
|
|
// Access: Private
|
|
// Description: The Python calls that implement do_callback(). This
|
|
// function is separate so we can acquire the Python
|
|
// interpretor lock while it runs.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PythonCallbackObject::
|
|
do_python_callback(CallbackData *cbdata) {
|
|
nassertv(cbdata != NULL);
|
|
|
|
// Wrap the cbdata up in a Python object, then put it in a tuple,
|
|
// for the argument list.
|
|
PyObject *pycbdata =
|
|
DTool_CreatePyInstanceTyped(cbdata, Dtool_TypedObject,
|
|
false, false, cbdata->get_type_index());
|
|
PyObject *args = Py_BuildValue("(O)", pycbdata);
|
|
Py_DECREF(pycbdata);
|
|
|
|
PyObject *result =
|
|
Thread::get_current_thread()->call_python_func(_function, args);
|
|
Py_DECREF(args);
|
|
|
|
if (result == (PyObject *)NULL) {
|
|
util_cat.error()
|
|
<< "Exception occurred in " << *this << "\n";
|
|
} else {
|
|
Py_DECREF(result);
|
|
}
|
|
}
|
|
|
|
#endif // HAVE_PYTHON
|