7#ifndef PXR_BASE_TF_PY_FUNCTION_H
8#define PXR_BASE_TF_PY_FUNCTION_H
13#include "pxr/base/tf/pyLock.h"
14#include "pxr/base/tf/pyObjWrapper.h"
17#include "pxr/external/boost/python/converter/from_python.hpp"
18#include "pxr/external/boost/python/converter/registered.hpp"
19#include "pxr/external/boost/python/converter/rvalue_from_python_data.hpp"
20#include "pxr/external/boost/python/extract.hpp"
21#include "pxr/external/boost/python/handle.hpp"
22#include "pxr/external/boost/python/object.hpp"
26PXR_NAMESPACE_OPEN_SCOPE
29struct TfPyFunctionFromPython;
31template <
typename Ret,
typename... Args>
32struct TfPyFunctionFromPython<Ret (Args...)>
38 Ret operator()(Args... args) {
48 Ret operator()(Args... args) {
49 using namespace pxr_boost::python;
52 PyObject *callablePtr;
53 if (Tf_PyWeakrefGetRef(weak.
ptr(), &callablePtr) != 1) {
54 TF_WARN(
"Tried to call an expired python callback");
57 object callable { handle<> { callablePtr } };
67 Ret operator()(Args... args) {
68 using namespace pxr_boost::python;
73 if (Tf_PyWeakrefGetRef(weakSelf.
ptr(), &selfPtr) != 1) {
74 TF_WARN(
"Tried to call a method on an expired python instance");
77 object self { handle<> { selfPtr } };
78 object method { handle<> { PyMethod_New(func.
ptr(), self.ptr()) } };
83 TfPyFunctionFromPython() {
84 RegisterFunctionType<std::function<Ret (Args...)>>();
87 template <
typename FuncType>
89 RegisterFunctionType() {
90 using namespace pxr_boost::python;
92 insert(&convertible, &construct<FuncType>, type_id<FuncType>());
95 static void *convertible(PyObject *obj) {
96 return ((obj == Py_None) || PyCallable_Check(obj)) ? obj : 0;
99 template <
typename FuncType>
100 static void construct(PyObject *src, pxr_boost::python::converter::
101 rvalue_from_python_stage1_data *data) {
103 using namespace pxr_boost::python;
105 void *storage = ((converter::rvalue_from_python_storage<FuncType> *)
106 data)->storage.bytes;
108 if (src == Py_None) {
109 new (storage) FuncType();
131 object callable(handle<>(borrowed(src)));
132 PyObject *pyCallable = callable.ptr();
134 PyMethod_Check(pyCallable) ?
135 PyMethod_GET_SELF(pyCallable) : NULL;
140 object func(handle<>(borrowed(PyMethod_GET_FUNCTION(
142 object weakSelf(handle<>(PyWeakref_NewRef(self, NULL)));
149 }
else if (PyObject_HasAttrString(pyCallable,
"__name__") &&
150 extract<string>(callable.attr(
"__name__"))()
156 if (PyObject *weakCallable =
157 PyWeakref_NewRef(pyCallable, NULL)) {
161 object(handle<>(weakCallable)))});
170 data->convertible = storage;
174PXR_NAMESPACE_CLOSE_SCOPE
Miscellaneous Utilities for dealing with script.
Convenience class for accessing the Python Global Interpreter Lock.
Boost Python object wrapper.
TF_API PyObject * ptr() const
Underlying PyObject* access.
#define TF_WARN(...)
Issue a warning, but continue execution.
Utilities for calling python callables.
Provide a way to call a Python callable.