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> 45 #include <type_traits> 49 PXR_NAMESPACE_OPEN_SCOPE
51 template <
typename Derived>
52 struct 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 PY_MAJOR_VERSION > 2 107 if (borrowed_f && PyCallable_Check(borrowed_f.get())) {
108 func_object = borrowed_f.get();
111 if (borrowed_f && PyMethod_Check(borrowed_f.get())) {
113 ((PyMethodObject*)borrowed_f.get())->im_func;
122 if (func_object != ((PyMethodObject*)m.get())->im_func)
128 return Override(handle<>(detail::none()));
131 Override GetPureOverride(
char const *func)
const {
133 Override ret = GetOverride(func);
140 (
"Pure virtual method '%s' called -- " 141 "must provide a python implementation.",
143 TfPyConvertPythonExceptionToTfErrors();
148 template <
typename Ret>
154 template <
class Ret,
class Cls,
typename... Arg>
155 std::function<Ret (Arg...)>
158 Ret (Cls::*defaultImpl)(Arg...));
160 template <
class Ret,
class Cls,
typename... Arg>
161 std::function<Ret (Arg...)>
164 Ret (Cls::*defaultImpl)(Arg...)
const)
const;
167 virtual ~TfPyPolymorphic();
173 template <
class Ret,
class Cls,
typename... Args>
176 using MemFn =
typename std::conditional<
177 std::is_const<Cls>::value,
178 Ret (Cls::*)(Args...)
const, Ret (Cls::*)(Args...)>::type;
180 _BindMemFn(MemFn memFn, Cls *obj)
186 operator()(Args... args)
const 188 return (_obj->*_memFn)(args...);
197 template <
typename Derived>
198 TfPyPolymorphic<Derived>::~TfPyPolymorphic()
202 template <
typename Derived>
203 template <
class Ret,
class Cls,
typename... Args>
205 std::function<Ret (Args...)>
206 TfPyPolymorphic<Derived>::CallVirtual(
208 Ret (Cls::*defaultImpl)(Args...))
210 static_assert(std::is_base_of<This, Cls>::value,
211 "This must be a base of Cls.");
213 if (Override o = GetOverride(fname))
215 return _BindMemFn<Ret, Cls, Args...>(
216 defaultImpl, static_cast<Cls *>(
this));
219 template <
typename Derived>
220 template <
class Ret,
class Cls,
typename... Args>
222 std::function<Ret (Args...)>
223 TfPyPolymorphic<Derived>::CallVirtual(
225 Ret (Cls::*defaultImpl)(Args...)
const)
const 227 static_assert(std::is_base_of<This, Cls>::value,
228 "This must be a base of Cls.");
230 if (Override o = GetOverride(fname))
232 return _BindMemFn<Ret, Cls
const, Args...>(
233 defaultImpl, static_cast<Cls const *>(
this));
236 PXR_NAMESPACE_CLOSE_SCOPE
240 namespace boost {
namespace python {
241 template <
typename T>
242 struct has_back_reference< PXR_NS::TfPyPolymorphic<T> >
246 PXR_NAMESPACE_OPEN_SCOPE
249 template <
typename Base,
typename Fn>
250 struct Tf_PyMemberFunctionPointerUpcast;
252 template <
typename Base,
typename Derived,
253 typename Ret,
typename... Args>
254 struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) >
256 typedef Ret (Base::*Type)(Args...);
259 template <
typename Base,
typename Derived,
260 typename Ret,
typename... Args>
261 struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) const >
263 typedef Ret (Base::*Type)(Args...)
const;
266 template <
typename Base,
typename Fn>
267 typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type
268 TfPyProtectedVirtual( Fn fn )
270 typedef typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type Ret;
272 return static_cast<Ret>(fn);
275 PXR_NAMESPACE_CLOSE_SCOPE
277 #endif // PXR_BASE_TF_PY_POLYMORPHIC_H TF_API std::string TfStringPrintf(const char *fmt,...)
Returns a string formed by a printf()-like specification.
Utilities for calling python callables.
Low-level utilities for informing users of various internal and external diagnostic conditions.
Pointer storage with deletion detection.
A reimplementation of boost::python::override.
Convenience class for accessing the Python Global Interpreter Lock.
Provide a way to call a Python callable.