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/type_traits.hpp>
43 #include <boost/python/has_back_reference.hpp>
46 #include <type_traits>
50 PXR_NAMESPACE_OPEN_SCOPE
52 template <
typename Derived>
53 struct TfPyPolymorphic :
54 public TfType::PyPolymorphicBase,
55 public boost::python::wrapper<Derived>
57 typedef TfPyPolymorphic<Derived> This;
60 Override GetOverride(
char const *func)
const {
63 using namespace boost::python;
69 PyObject * m_self = detail::wrapper_base_::get_owner(*
this);
75 if (handle<> m = handle<>(
77 PyObject_GetAttrString(
78 m_self, const_cast<char*>(func))))
83 type_handle typeHandle =
84 objects::registered_class_object(
86 PyTypeObject* class_object = typeHandle.get();
88 PyObject* func_object = 0;
91 PyMethod_Check(m.get())
92 && ((PyMethodObject*)m.get())->im_self == m_self
93 && class_object->tp_dict != 0
99 PyObject_GetAttrString(
100 (PyObject *)class_object,
101 const_cast<char*>(func))));
107 if (borrowed_f && PyMethod_Check(borrowed_f.get())) {
109 ((PyMethodObject*)borrowed_f.get())->im_func;
117 if (func_object != ((PyMethodObject*)m.get())->im_func)
123 return Override(handle<>(detail::none()));
126 Override GetPureOverride(
char const *func)
const {
128 Override ret = GetOverride(func);
135 (
"Pure virtual method '%s' called -- "
136 "must provide a python implementation.",
138 TfPyConvertPythonExceptionToTfErrors();
143 template <
typename Ret>
149 template <
class Ret,
class Cls,
typename... Arg>
150 std::function<Ret (Arg...)>
153 Ret (Cls::*defaultImpl)(Arg...));
155 template <
class Ret,
class Cls,
typename... Arg>
156 std::function<Ret (Arg...)>
159 Ret (Cls::*defaultImpl)(Arg...)
const)
const;
162 virtual ~TfPyPolymorphic();
168 template <
class Ret,
class Cls,
typename... Args>
171 using MemFn =
typename std::conditional<
172 std::is_const<Cls>::value,
173 Ret (Cls::*)(Args...)
const, Ret (Cls::*)(Args...)>::type;
175 _BindMemFn(MemFn memFn, Cls *obj)
181 operator()(Args... args)
const
183 return (_obj->*_memFn)(args...);
192 template <
typename Derived>
193 TfPyPolymorphic<Derived>::~TfPyPolymorphic()
197 template <
typename Derived>
198 template <
class Ret,
class Cls,
typename... Args>
200 std::function<Ret (Args...)>
201 TfPyPolymorphic<Derived>::CallVirtual(
203 Ret (Cls::*defaultImpl)(Args...))
205 static_assert(std::is_base_of<This, Cls>::value,
206 "This must be a base of Cls.");
208 if (Override o = GetOverride(fname))
210 return _BindMemFn<Ret, Cls, Args...>(
211 defaultImpl,
static_cast<Cls *
>(
this));
214 template <
typename Derived>
215 template <
class Ret,
class Cls,
typename... Args>
217 std::function<Ret (Args...)>
218 TfPyPolymorphic<Derived>::CallVirtual(
220 Ret (Cls::*defaultImpl)(Args...)
const)
const
222 static_assert(std::is_base_of<This, Cls>::value,
223 "This must be a base of Cls.");
225 if (Override o = GetOverride(fname))
227 return _BindMemFn<Ret, Cls
const, Args...>(
228 defaultImpl,
static_cast<Cls
const *
>(
this));
231 PXR_NAMESPACE_CLOSE_SCOPE
235 namespace boost {
namespace python {
236 template <
typename T>
237 struct has_back_reference< PXR_NS::TfPyPolymorphic<T> >
241 PXR_NAMESPACE_OPEN_SCOPE
244 template <
typename Base,
typename Fn>
245 struct Tf_PyMemberFunctionPointerUpcast;
247 template <
typename Base,
typename Derived,
248 typename Ret,
typename... Args>
249 struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) >
251 typedef Ret (Base::*Type)(Args...);
254 template <
typename Base,
typename Derived,
255 typename Ret,
typename... Args>
256 struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) const >
258 typedef Ret (Base::*Type)(Args...)
const;
261 template <
typename Base,
typename Fn>
262 typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type
263 TfPyProtectedVirtual( Fn fn )
265 typedef typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type Ret;
267 return static_cast<Ret
>(fn);
270 PXR_NAMESPACE_CLOSE_SCOPE
272 #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.
Provide a way to call a Python callable.