7#ifndef PXR_BASE_TF_PY_POLYMORPHIC_H
8#define PXR_BASE_TF_PY_POLYMORPHIC_H
14#include "pxr/base/tf/pyOverride.h"
20#include "pxr/base/tf/pyLock.h"
21#include "pxr/base/tf/type.h"
23#include "pxr/external/boost/python/object/class_detail.hpp"
24#include "pxr/external/boost/python/wrapper.hpp"
25#include "pxr/external/boost/python/has_back_reference.hpp"
32PXR_NAMESPACE_OPEN_SCOPE
34template <
typename Derived>
35struct TfPyPolymorphic :
36 public TfType::PyPolymorphicBase,
37 public pxr_boost::python::wrapper<Derived>
39 typedef TfPyPolymorphic<Derived> This;
42 Override GetOverride(
char const *func)
const {
45 using namespace pxr_boost::python;
51 PyObject * m_self = detail::wrapper_base_::get_owner(*
this);
57 if (handle<> m = handle<>(
59 PyObject_GetAttrString(
60 m_self,
const_cast<char*
>(func))))
65 type_handle typeHandle =
66 objects::registered_class_object(
68 PyTypeObject* class_object = typeHandle.get();
70 PyObject* func_object = 0;
73 PyMethod_Check(m.get())
74 && ((PyMethodObject*)m.get())->im_self == m_self
75 && class_object->tp_dict != 0
81 PyObject_GetAttrString(
82 (PyObject *)class_object,
83 const_cast<char*
>(func))));
89 if (borrowed_f && PyCallable_Check(borrowed_f.get())) {
90 func_object = borrowed_f.get();
98 if (func_object != ((PyMethodObject*)m.get())->im_func)
104 return Override(handle<>(detail::none()));
107 Override GetPureOverride(
char const *func)
const {
109 Override ret = GetOverride(func);
116 (
"Pure virtual method '%s' called -- "
117 "must provide a python implementation.",
119 TfPyConvertPythonExceptionToTfErrors();
124 template <
typename Ret>
130 template <
class Ret,
class Cls,
typename... Arg>
131 std::function<Ret (Arg...)>
134 Ret (Cls::*defaultImpl)(Arg...));
136 template <
class Ret,
class Cls,
typename... Arg>
137 std::function<Ret (Arg...)>
140 Ret (Cls::*defaultImpl)(Arg...)
const)
const;
143 virtual ~TfPyPolymorphic();
149 template <
class Ret,
class Cls,
typename... Args>
152 using MemFn =
typename std::conditional<
153 std::is_const<Cls>::value,
154 Ret (Cls::*)(Args...)
const, Ret (Cls::*)(Args...)>::type;
156 _BindMemFn(MemFn memFn, Cls *obj)
162 operator()(Args... args)
const
164 return (_obj->*_memFn)(args...);
173template <
typename Derived>
174TfPyPolymorphic<Derived>::~TfPyPolymorphic()
178template <
typename Derived>
179template <
class Ret,
class Cls,
typename... Args>
181std::function<Ret (Args...)>
182TfPyPolymorphic<Derived>::CallVirtual(
184 Ret (Cls::*defaultImpl)(Args...))
186 static_assert(std::is_base_of<This, Cls>::value,
187 "This must be a base of Cls.");
189 if (Override o = GetOverride(fname))
191 return _BindMemFn<Ret, Cls, Args...>(
192 defaultImpl,
static_cast<Cls *
>(
this));
195template <
typename Derived>
196template <
class Ret,
class Cls,
typename... Args>
198std::function<Ret (Args...)>
199TfPyPolymorphic<Derived>::CallVirtual(
201 Ret (Cls::*defaultImpl)(Args...)
const)
const
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
const, Args...>(
209 defaultImpl,
static_cast<Cls
const *
>(
this));
212PXR_NAMESPACE_CLOSE_SCOPE
216namespace PXR_BOOST_NAMESPACE {
namespace python {
217 template <
typename T>
218 struct has_back_reference< PXR_NS::TfPyPolymorphic<T> >
222PXR_NAMESPACE_OPEN_SCOPE
225template <
typename Base,
typename Fn>
226struct Tf_PyMemberFunctionPointerUpcast;
228template <
typename Base,
typename Derived,
229 typename Ret,
typename... Args>
230struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) >
232 typedef Ret (Base::*Type)(Args...);
235template <
typename Base,
typename Derived,
236 typename Ret,
typename... Args>
237struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) const >
239 typedef Ret (Base::*Type)(Args...)
const;
242template <
typename Base,
typename Fn>
243typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type
244TfPyProtectedVirtual( Fn fn )
246 typedef typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type Ret;
248 return static_cast<Ret
>(fn);
251PXR_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 pxr_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.