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 PY_MAJOR_VERSION > 2 108 if (borrowed_f && PyCallable_Check(borrowed_f.get())) {
109 func_object = borrowed_f.get();
112 if (borrowed_f && PyMethod_Check(borrowed_f.get())) {
114 ((PyMethodObject*)borrowed_f.get())->im_func;
123 if (func_object != ((PyMethodObject*)m.get())->im_func)
129 return Override(handle<>(detail::none()));
132 Override GetPureOverride(
char const *func)
const {
134 Override ret = GetOverride(func);
141 (
"Pure virtual method '%s' called -- " 142 "must provide a python implementation.",
144 TfPyConvertPythonExceptionToTfErrors();
149 template <
typename Ret>
155 template <
class Ret,
class Cls,
typename... Arg>
156 std::function<Ret (Arg...)>
159 Ret (Cls::*defaultImpl)(Arg...));
161 template <
class Ret,
class Cls,
typename... Arg>
162 std::function<Ret (Arg...)>
165 Ret (Cls::*defaultImpl)(Arg...)
const)
const;
168 virtual ~TfPyPolymorphic();
174 template <
class Ret,
class Cls,
typename... Args>
177 using MemFn =
typename std::conditional<
178 std::is_const<Cls>::value,
179 Ret (Cls::*)(Args...)
const, Ret (Cls::*)(Args...)>::type;
181 _BindMemFn(MemFn memFn, Cls *obj)
187 operator()(Args... args)
const 189 return (_obj->*_memFn)(args...);
198 template <
typename Derived>
199 TfPyPolymorphic<Derived>::~TfPyPolymorphic()
203 template <
typename Derived>
204 template <
class Ret,
class Cls,
typename... Args>
206 std::function<Ret (Args...)>
207 TfPyPolymorphic<Derived>::CallVirtual(
209 Ret (Cls::*defaultImpl)(Args...))
211 static_assert(std::is_base_of<This, Cls>::value,
212 "This must be a base of Cls.");
214 if (Override o = GetOverride(fname))
216 return _BindMemFn<Ret, Cls, Args...>(
217 defaultImpl, static_cast<Cls *>(
this));
220 template <
typename Derived>
221 template <
class Ret,
class Cls,
typename... Args>
223 std::function<Ret (Args...)>
224 TfPyPolymorphic<Derived>::CallVirtual(
226 Ret (Cls::*defaultImpl)(Args...)
const)
const 228 static_assert(std::is_base_of<This, Cls>::value,
229 "This must be a base of Cls.");
231 if (Override o = GetOverride(fname))
233 return _BindMemFn<Ret, Cls
const, Args...>(
234 defaultImpl, static_cast<Cls const *>(
this));
237 PXR_NAMESPACE_CLOSE_SCOPE
241 namespace boost {
namespace python {
242 template <
typename T>
243 struct has_back_reference< PXR_NS::TfPyPolymorphic<T> >
247 PXR_NAMESPACE_OPEN_SCOPE
250 template <
typename Base,
typename Fn>
251 struct Tf_PyMemberFunctionPointerUpcast;
253 template <
typename Base,
typename Derived,
254 typename Ret,
typename... Args>
255 struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) >
257 typedef Ret (Base::*Type)(Args...);
260 template <
typename Base,
typename Derived,
261 typename Ret,
typename... Args>
262 struct Tf_PyMemberFunctionPointerUpcast< Base, Ret (Derived::*)(Args...) const >
264 typedef Ret (Base::*Type)(Args...)
const;
267 template <
typename Base,
typename Fn>
268 typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type
269 TfPyProtectedVirtual( Fn fn )
271 typedef typename Tf_PyMemberFunctionPointerUpcast<Base, Fn>::Type Ret;
273 return static_cast<Ret>(fn);
276 PXR_NAMESPACE_CLOSE_SCOPE
278 #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.