24#ifndef PXR_BASE_TF_PY_POLYMORPHIC_H
25#define PXR_BASE_TF_PY_POLYMORPHIC_H
31#include "pxr/base/tf/pyOverride.h"
37#include "pxr/base/tf/pyLock.h"
38#include "pxr/base/tf/type.h"
40#include <boost/python/object/class_detail.hpp>
41#include <boost/python/wrapper.hpp>
42#include <boost/python/has_back_reference.hpp>
49PXR_NAMESPACE_OPEN_SCOPE
51template <
typename Derived>
52struct TfPyPolymorphic :
53 public TfType::PyPolymorphicBase,
54 public boost::python::wrapper<Derived>
56 typedef TfPyPolymorphic<Derived> This;
59 Override GetOverride(
char const *func)
const {
62 using namespace boost::python;
68 PyObject * m_self = detail::wrapper_base_::get_owner(*
this);
74 if (handle<> m = handle<>(
76 PyObject_GetAttrString(
77 m_self,
const_cast<char*
>(func))))
82 type_handle typeHandle =
83 objects::registered_class_object(
85 PyTypeObject* class_object = typeHandle.get();
87 PyObject* func_object = 0;
90 PyMethod_Check(m.get())
91 && ((PyMethodObject*)m.get())->im_self == m_self
92 && class_object->tp_dict != 0
98 PyObject_GetAttrString(
99 (PyObject *)class_object,
100 const_cast<char*
>(func))));
106 if (borrowed_f && PyCallable_Check(borrowed_f.get())) {
107 func_object = borrowed_f.get();
115 if (func_object != ((PyMethodObject*)m.get())->im_func)
121 return Override(handle<>(detail::none()));
124 Override GetPureOverride(
char const *func)
const {
126 Override ret = GetOverride(func);
133 (
"Pure virtual method '%s' called -- "
134 "must provide a python implementation.",
136 TfPyConvertPythonExceptionToTfErrors();
141 template <
typename Ret>
147 template <
class Ret,
class Cls,
typename... Arg>
148 std::function<Ret (Arg...)>
151 Ret (Cls::*defaultImpl)(Arg...));
153 template <
class Ret,
class Cls,
typename... Arg>
154 std::function<Ret (Arg...)>
157 Ret (Cls::*defaultImpl)(Arg...)
const)
const;
160 virtual ~TfPyPolymorphic();
166 template <
class Ret,
class Cls,
typename... Args>
169 using MemFn =
typename std::conditional<
170 std::is_const<Cls>::value,
171 Ret (Cls::*)(Args...)
const, Ret (Cls::*)(Args...)>::type;
173 _BindMemFn(MemFn memFn, Cls *obj)
179 operator()(Args... args)
const
181 return (_obj->*_memFn)(args...);
190template <
typename Derived>
191TfPyPolymorphic<Derived>::~TfPyPolymorphic()
195template <
typename Derived>
196template <
class Ret,
class Cls,
typename... Args>
198std::function<Ret (Args...)>
199TfPyPolymorphic<Derived>::CallVirtual(
201 Ret (Cls::*defaultImpl)(Args...))
203 static_assert(std::is_base_of<This, Cls>::value,
204 "This must be a base of Cls.");
206 if (Override o = GetOverride(fname))
208 return _BindMemFn<Ret, Cls, Args...>(
209 defaultImpl,
static_cast<Cls *
>(
this));
212template <
typename Derived>
213template <
class Ret,
class Cls,
typename... Args>
215std::function<Ret (Args...)>
216TfPyPolymorphic<Derived>::CallVirtual(
218 Ret (Cls::*defaultImpl)(Args...)
const)
const
220 static_assert(std::is_base_of<This, Cls>::value,
221 "This must be a base of Cls.");
223 if (Override o = GetOverride(fname))
225 return _BindMemFn<Ret, Cls
const, Args...>(
226 defaultImpl,
static_cast<Cls
const *
>(
this));
229PXR_NAMESPACE_CLOSE_SCOPE
233namespace boost {
namespace python {
234 template <
typename T>
235 struct has_back_reference< PXR_NS::TfPyPolymorphic<T> >
239PXR_NAMESPACE_OPEN_SCOPE
242template <
typename Base,
typename Fn>
243struct Tf_PyMemberFunctionPointerUpcast;
245template <
typename Base,
typename Derived,
246 typename Ret,
typename... Args>
247struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) >
249 typedef Ret (Base::*Type)(Args...);
252template <
typename Base,
typename Derived,
253 typename Ret,
typename... Args>
254struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) const >
256 typedef Ret (Base::*Type)(Args...)
const;
259template <
typename Base,
typename Fn>
260typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type
261TfPyProtectedVirtual( Fn fn )
263 typedef typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type Ret;
265 return static_cast<Ret
>(fn);
268PXR_NAMESPACE_CLOSE_SCOPE
Low-level utilities for informing users of various internal and external diagnostic conditions.
Convenience class for accessing the Python Global Interpreter Lock.
A reimplementation of boost::python::override.
TF_API std::string TfStringPrintf(const char *fmt,...)
Returns a string formed by a printf()-like specification.
Utilities for calling python callables.
Provide a way to call a Python callable.
Pointer storage with deletion detection.