24 #ifndef PXR_BASE_TF_PY_PTR_HELPERS_H 25 #define PXR_BASE_TF_PY_PTR_HELPERS_H 33 #include "pxr/base/tf/pyIdentity.h" 34 #include "pxr/base/tf/pyObjectFinder.h" 35 #include "pxr/base/tf/wrapTypeHelpers.h" 44 #include <boost/python/class.hpp> 45 #include <boost/python/converter/from_python.hpp> 46 #include <boost/python/converter/registered.hpp> 47 #include <boost/python/converter/registrations.hpp> 48 #include <boost/python/converter/registry.hpp> 49 #include <boost/python/converter/rvalue_from_python_data.hpp> 50 #include <boost/python/converter/to_python_function_type.hpp> 51 #include <boost/python/def_visitor.hpp> 52 #include <boost/python/handle.hpp> 53 #include <boost/python/implicit.hpp> 54 #include <boost/python/to_python_converter.hpp> 58 PXR_NAMESPACE_OPEN_SCOPE
77 template <
typename Ptr>
79 typedef typename Ptr::DataType Pointee;
80 typedef boost::python::objects::pointer_holder<Ptr, Pointee> Holder;
81 typedef std::pair<PyObject*, bool> Result;
86 static Result Execute(Ptr
const& p)
89 if (!p.GetUniqueIdentifier())
90 return Result(boost::python::detail::none(),
false);
98 if (PyObject *
id = Tf_PyGetPythonIdentity(p))
99 return Result(
id,
false);
103 PyObject *res = boost::python::objects::make_ptr_instance
104 <Pointee, Holder>::execute(p);
107 return Result(res, res != Py_None);
111 namespace Tf_PyDefHelpers {
113 using namespace boost::python;
115 template <
typename Ptr>
116 struct _PtrInterface {
117 typedef typename Ptr::DataType Pointee;
118 typedef typename boost::add_const<Pointee>::type ConstPointee;
119 typedef typename boost::remove_const<Pointee>::type NonConstPointee;
121 template <
typename U>
123 typedef typename Ptr::template Rebind<U>::Type Type;
126 typedef typename Rebind<ConstPointee>::Type ConstPtr;
127 typedef typename Rebind<NonConstPointee>::Type NonConstPtr;
131 template <
typename PtrType>
132 bool _IsPtrExpired(
object const &
self) {
134 PtrType p = extract<PtrType>(
self);
136 }
catch (boost::python::error_already_set
const &) {
142 template <
typename PtrType>
143 bool _IsPtrValid(
object const &
self) {
144 return !_IsPtrExpired<PtrType>(
self);
147 template <
typename PtrType>
148 bool _ArePtrsEqual(PtrType
const &
self,
149 PtrType
const &other) {
return self == other; }
150 template <
typename PtrType>
151 bool _ArePtrsNotEqual(PtrType
const &
self,
152 PtrType
const &other) {
return self != other; }
153 template <
typename PtrType>
154 bool _ArePtrsLessThan(PtrType
const &
self,
155 PtrType
const &other) {
return self < other; }
159 template <
class PtrType>
160 struct _PtrFromPythonConversionPolicy {
161 static void Apply(PtrType
const &, PyObject *) { }
166 template <
typename T>
167 struct _PtrFromPythonConversionPolicy<
TfRefPtr<T> > {
168 static void Apply(
TfRefPtr<T> const &p, PyObject *obj) {
169 Tf_PyRemovePythonOwnership(p, obj);
174 struct _PtrFromPython {
175 typedef typename _PtrInterface<Ptr>::Pointee Pointee;
177 converter::registry::insert(&convertible, &construct,
181 static void *convertible(PyObject *p) {
184 void *result = converter::get_lvalue_from_python
185 (p, converter::registered<Pointee>::converters);
189 static void construct(PyObject* source, converter::
190 rvalue_from_python_stage1_data* data) {
191 void*
const storage = ((converter::rvalue_from_python_storage<Ptr>*)
192 data)->storage.bytes;
194 if (data->convertible == source)
197 Ptr ptr(static_cast<Pointee*>(data->convertible));
198 new (storage) Ptr(ptr);
199 _PtrFromPythonConversionPolicy<Ptr>::Apply(ptr, source);
202 Tf_PySetPythonIdentity(ptr, source);
204 data->convertible = storage;
211 template <
typename PtrType>
212 struct _AnyWeakPtrFromPython {
214 _AnyWeakPtrFromPython() {
215 converter::registry::insert(&convertible, &construct,
216 type_id<TfAnyWeakPtr>());
219 static void *convertible(PyObject *p) {
222 void *result = converter::get_lvalue_from_python
223 (p, converter::registered
224 <
typename _PtrInterface<PtrType>::Pointee>::converters);
228 static void construct(PyObject* source, converter::
229 rvalue_from_python_stage1_data* data) {
230 void*
const storage = ((converter::rvalue_from_python_storage
233 if (data->convertible == source)
236 typedef typename _PtrInterface<PtrType>::Pointee T;
237 T *ptr = static_cast<T*>(data->convertible);
238 PtrType smartPtr(ptr);
242 data->convertible = storage;
246 template <
typename Ptr>
247 struct _ConstPtrToPython {
248 typedef typename _PtrInterface<Ptr>::ConstPtr ConstPtr;
249 typedef typename _PtrInterface<Ptr>::NonConstPtr NonConstPtr;
250 _ConstPtrToPython() {
251 to_python_converter<ConstPtr, _ConstPtrToPython<Ptr> >();
253 static PyObject *convert(ConstPtr
const &p) {
254 return incref(
object(TfConst_cast<NonConstPtr>(p)).ptr());
258 template <
typename Ptr>
259 struct _PtrToPython {
261 to_python_converter<Ptr, _PtrToPython<Ptr> >();
263 static PyObject *convert(Ptr
const &p) {
264 std::pair<PyObject*, bool> ret = TfMakePyPtr<Ptr>::Execute(p);
266 Tf_PySetPythonIdentity(p, ret.first);
272 template <
typename SrcPtr,
typename DstPtr>
273 struct _ConvertPtrToPython {
274 _ConvertPtrToPython() {
275 to_python_converter<SrcPtr, _ConvertPtrToPython<SrcPtr, DstPtr> >();
277 static PyObject *convert(SrcPtr
const &p) {
279 return incref(
object(dst).ptr());
283 template <
typename Ptr>
284 struct _PtrToPythonWrapper {
289 static converter::to_python_function_t _originalConverter;
292 static PyObject *Convert(
void const *x) {
294 Ptr
const &p = *static_cast<Ptr const *>(x);
296 std::pair<PyObject*, bool> ret = TfMakePyPtr<Ptr>::Execute(p);
297 if (ret.first == Py_None) {
299 Py_DECREF(ret.first);
300 ret.first = _originalConverter(x);
303 Tf_PySetPythonIdentity(p, ret.first);
308 template <
typename T>
309 converter::to_python_function_t
310 _PtrToPythonWrapper<T>::_originalConverter = 0;
312 struct WeakPtr : def_visitor<WeakPtr> {
313 friend class def_visitor_access;
315 template <
typename WrapperPtrType,
typename Wrapper,
typename T>
316 static void _RegisterConversions(Wrapper *, T *) {
317 _RegisterConversionsHelper<WrapperPtrType, Wrapper, T>();
320 template <
typename WrapperPtrType,
typename Wrapper,
typename T>
321 static void _RegisterConversionsHelper() {
323 static_assert(std::is_same<
324 typename _PtrInterface<WrapperPtrType>::Pointee,
326 "Pointee must be same type as Wrapper.");
329 _PtrInterface<WrapperPtrType>::template Rebind<T>::Type PtrType;
332 _PtrFromPython<PtrType>();
335 _AnyWeakPtrFromPython<PtrType>();
338 implicitly_convertible<PtrType,
339 typename _PtrInterface<PtrType>::ConstPtr >();
342 _ConstPtrToPython<PtrType>();
352 converter::registration *r = const_cast<converter::registration *>
353 (converter::registry::query(type_id<WrapperPtrType>()));
355 _PtrToPythonWrapper<WrapperPtrType>::
356 _originalConverter = r->m_to_python;
357 r->m_to_python = _PtrToPythonWrapper<WrapperPtrType>::Convert;
365 if (!std::is_same<Wrapper, T>::value)
366 _PtrToPython<PtrType>();
370 template <
typename PtrType,
typename CLS,
typename Wrapper,
typename T>
371 static void _AddAPI(CLS &c, Wrapper *, T *) {
373 _PtrInterface<PtrType>::template Rebind<T>::Type UnwrappedPtrType;
375 c.add_property(
"expired", _IsPtrExpired<UnwrappedPtrType>,
377 "True if this object has expired, False otherwise.");
378 c.def(TfPyBoolBuiltinFuncName, _IsPtrValid<UnwrappedPtrType>,
380 "True if this object has not expired. False otherwise.");
381 c.def(
"__eq__", _ArePtrsEqual<UnwrappedPtrType>,
382 "Equality operator: x == y");
383 c.def(
"__ne__", _ArePtrsNotEqual<UnwrappedPtrType>,
384 "Non-equality operator: x != y");
385 c.def(
"__lt__", _ArePtrsLessThan<UnwrappedPtrType>,
386 "Less than operator: x < y");
390 template <
typename CLS>
391 void visit(CLS &c)
const {
392 typedef typename CLS::wrapped_type Type;
393 typedef typename CLS::metadata::held_type_arg PtrType;
394 static_assert(TF_SUPPORTS_WEAKPTR(Type),
395 "Type must support TfWeakPtr.");
397 _RegisterConversions<PtrType>
398 ((Type *)0, detail::unwrap_wrapper((Type *)0));
401 Tf_RegisterPythonObjectFinder<Type, PtrType>();
404 _AddAPI<PtrType>(c, (Type *)0, detail::unwrap_wrapper((Type *)0));
408 struct RefAndWeakPtr : def_visitor<RefAndWeakPtr> {
409 friend class def_visitor_access;
411 template <
typename CLS,
typename Wrapper,
typename T>
412 static void _AddAPI(Wrapper *, T *) {
413 _PtrFromPython<TfRefPtr<T> >();
415 _PtrInterface<typename CLS::metadata::held_type>::template
416 Rebind<T>::Type PtrType;
417 _ConvertPtrToPython<TfRefPtr<T>, PtrType>();
420 template <
typename CLS>
421 void visit(CLS &c)
const {
422 typedef typename CLS::wrapped_type Type;
423 static_assert(TF_SUPPORTS_REFPTR(Type),
424 "Type must support TfRefPtr.");
427 _AddAPI<CLS>((Type *)0, detail::unwrap_wrapper((Type *)0));
433 struct TfPyWeakPtr : Tf_PyDefHelpers::WeakPtr {};
434 struct TfPyRefAndWeakPtr : Tf_PyDefHelpers::RefAndWeakPtr {};
436 PXR_NAMESPACE_CLOSE_SCOPE
438 #endif // PXR_BASE_TF_PY_PTR_HELPERS_H Compatibility code for supporting python 2 and 3.
A boost.python visitor that associates the Python class object created by the wrapping with the TfTyp...
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
ARCH_API std::string ArchGetDemangled(const std::string &typeName)
Return demangled RTTI-generated type name.
Type independent WeakPtr holder class.
Definitions of basic string utilities in tf.
Low-level utilities for informing users of various internal and external diagnostic conditions.
Pointer storage with deletion detection.
Demangle C++ typenames generated by the typeid() facility.
Provides the ability to hold an arbitrary TfWeakPtr in a non-type-specific manner in order to observe...
Reference-counted smart pointer utility class.