7#ifndef PXR_BASE_TF_PY_PTR_HELPERS_H
8#define PXR_BASE_TF_PY_PTR_HELPERS_H
15#include "pxr/base/tf/pyIdentity.h"
16#include "pxr/base/tf/pyObjectFinder.h"
17#include "pxr/base/tf/wrapTypeHelpers.h"
26#include "pxr/external/boost/python/class.hpp"
27#include "pxr/external/boost/python/converter/from_python.hpp"
28#include "pxr/external/boost/python/converter/registered.hpp"
29#include "pxr/external/boost/python/converter/registrations.hpp"
30#include "pxr/external/boost/python/converter/registry.hpp"
31#include "pxr/external/boost/python/converter/rvalue_from_python_data.hpp"
32#include "pxr/external/boost/python/converter/to_python_function_type.hpp"
33#include "pxr/external/boost/python/def_visitor.hpp"
34#include "pxr/external/boost/python/handle.hpp"
35#include "pxr/external/boost/python/implicit.hpp"
36#include "pxr/external/boost/python/to_python_converter.hpp"
41PXR_NAMESPACE_OPEN_SCOPE
60template <
typename Ptr>
62 typedef typename Ptr::DataType Pointee;
63 typedef pxr_boost::python::objects::pointer_holder<Ptr, Pointee> Holder;
64 typedef std::pair<PyObject*, bool> Result;
69 static Result Execute(Ptr
const& p)
72 if (!p.GetUniqueIdentifier())
73 return Result(pxr_boost::python::detail::none(),
false);
81 if (PyObject *
id = Tf_PyGetPythonIdentity(p))
82 return Result(
id,
false);
86 PyObject *res = pxr_boost::python::objects::make_ptr_instance
87 <Pointee, Holder>::execute(p);
90 return Result(res, res != Py_None);
94namespace Tf_PyDefHelpers {
96using namespace pxr_boost::python;
98template <
typename Ptr>
100 typedef typename Ptr::DataType Pointee;
101 using ConstPointee = std::add_const_t<Pointee>;
102 using NonConstPointee = std::remove_const_t<Pointee>;
104 template <
typename U>
106 typedef typename Ptr::template Rebind<U>::Type Type;
109 typedef typename Rebind<ConstPointee>::Type ConstPtr;
110 typedef typename Rebind<NonConstPointee>::Type NonConstPtr;
114template <
typename PtrType>
115bool _IsPtrExpired(
object const &self) {
117 PtrType p = extract<PtrType>(self);
119 }
catch (pxr_boost::python::error_already_set
const &) {
125template <
typename PtrType>
126bool _IsPtrValid(
object const &self) {
127 return !_IsPtrExpired<PtrType>(self);
130template <
typename PtrType>
131bool _ArePtrsEqual(PtrType
const &self,
132 PtrType
const &other) {
return self == other; }
133template <
typename PtrType>
134bool _ArePtrsNotEqual(PtrType
const &self,
135 PtrType
const &other) {
return self != other; }
136template <
typename PtrType>
137bool _ArePtrsLessThan(PtrType
const &self,
138 PtrType
const &other) {
return self < other; }
142template <
class PtrType>
143struct _PtrFromPythonConversionPolicy {
144 static void Apply(PtrType
const &, PyObject *) { }
150struct _PtrFromPythonConversionPolicy<
TfRefPtr<T> > {
151 static void Apply(
TfRefPtr<T> const &p, PyObject *obj) {
152 Tf_PyRemovePythonOwnership(p, obj);
157struct _PtrFromPython {
158 typedef typename _PtrInterface<Ptr>::Pointee Pointee;
160 converter::registry::insert(&convertible, &construct,
164 static void *convertible(PyObject *p) {
167 void *result = converter::get_lvalue_from_python
168 (p, converter::registered<Pointee>::converters);
172 static void construct(PyObject* source, converter::
173 rvalue_from_python_stage1_data* data) {
174 void*
const storage = ((converter::rvalue_from_python_storage<Ptr>*)
175 data)->storage.bytes;
177 if (data->convertible == source)
180 Ptr ptr(
static_cast<Pointee*
>(data->convertible));
181 new (storage) Ptr(ptr);
182 _PtrFromPythonConversionPolicy<Ptr>::Apply(ptr, source);
185 Tf_PySetPythonIdentity(ptr, source);
187 data->convertible = storage;
194template <
typename PtrType>
195struct _AnyWeakPtrFromPython {
197 _AnyWeakPtrFromPython() {
198 converter::registry::insert(&convertible, &construct,
199 type_id<TfAnyWeakPtr>());
202 static void *convertible(PyObject *p) {
205 void *result = converter::get_lvalue_from_python
206 (p, converter::registered
207 <
typename _PtrInterface<PtrType>::Pointee>::converters);
211 static void construct(PyObject* source, converter::
212 rvalue_from_python_stage1_data* data) {
213 void*
const storage = ((converter::rvalue_from_python_storage
216 if (data->convertible == source)
219 typedef typename _PtrInterface<PtrType>::Pointee T;
220 T *ptr =
static_cast<T*
>(data->convertible);
221 PtrType smartPtr(ptr);
225 data->convertible = storage;
229template <
typename Ptr>
230struct _ConstPtrToPython {
231 typedef typename _PtrInterface<Ptr>::ConstPtr ConstPtr;
232 typedef typename _PtrInterface<Ptr>::NonConstPtr NonConstPtr;
233 _ConstPtrToPython() {
234 to_python_converter<ConstPtr, _ConstPtrToPython<Ptr> >();
236 static PyObject *convert(ConstPtr
const &p) {
237 return incref(
object(TfConst_cast<NonConstPtr>(p)).ptr());
241template <
typename Ptr>
244 to_python_converter<Ptr, _PtrToPython<Ptr> >();
246 static PyObject *convert(Ptr
const &p) {
247 std::pair<PyObject*, bool> ret = TfMakePyPtr<Ptr>::Execute(p);
249 Tf_PySetPythonIdentity(p, ret.first);
255template <
typename SrcPtr,
typename DstPtr>
256struct _ConvertPtrToPython {
257 _ConvertPtrToPython() {
258 to_python_converter<SrcPtr, _ConvertPtrToPython<SrcPtr, DstPtr> >();
260 static PyObject *convert(SrcPtr
const &p) {
262 return incref(
object(dst).ptr());
266template <
typename Ptr>
267struct _PtrToPythonWrapper {
272 static converter::to_python_function_t _originalConverter;
275 static PyObject *Convert(
void const *x) {
277 Ptr
const &p = *
static_cast<Ptr
const *
>(x);
279 std::pair<PyObject*, bool> ret = TfMakePyPtr<Ptr>::Execute(p);
280 if (ret.first == Py_None) {
282 Py_DECREF(ret.first);
283 ret.first = _originalConverter(x);
286 Tf_PySetPythonIdentity(p, ret.first);
292converter::to_python_function_t
293_PtrToPythonWrapper<T>::_originalConverter = 0;
295struct WeakPtr : def_visitor<WeakPtr> {
296 friend class def_visitor_access;
298 template <
typename WrapperPtrType,
typename Wrapper,
typename T>
299 static void _RegisterConversions(Wrapper *, T *) {
300 _RegisterConversionsHelper<WrapperPtrType, Wrapper, T>();
303 template <
typename WrapperPtrType,
typename Wrapper,
typename T>
304 static void _RegisterConversionsHelper() {
306 static_assert(std::is_same<
307 typename _PtrInterface<WrapperPtrType>::Pointee,
309 "Pointee must be same type as Wrapper.");
312 _PtrInterface<WrapperPtrType>::template Rebind<T>::Type PtrType;
315 _PtrFromPython<PtrType>();
318 _AnyWeakPtrFromPython<PtrType>();
321 implicitly_convertible<PtrType,
322 typename _PtrInterface<PtrType>::ConstPtr >();
325 _ConstPtrToPython<PtrType>();
335 converter::registration *r =
const_cast<converter::registration *
>
336 (converter::registry::query(type_id<WrapperPtrType>()));
338 _PtrToPythonWrapper<WrapperPtrType>::
339 _originalConverter = r->m_to_python;
340 r->m_to_python = _PtrToPythonWrapper<WrapperPtrType>::Convert;
348 if (!std::is_same<Wrapper, T>::value)
349 _PtrToPython<PtrType>();
353 template <
typename PtrType,
typename CLS,
typename Wrapper,
typename T>
354 static void _AddAPI(CLS &c, Wrapper *, T *) {
356 _PtrInterface<PtrType>::template Rebind<T>::Type UnwrappedPtrType;
358 c.add_property(
"expired", _IsPtrExpired<UnwrappedPtrType>,
360 "True if this object has expired, False otherwise.");
361 c.def(
"__bool__", _IsPtrValid<UnwrappedPtrType>,
363 "True if this object has not expired. False otherwise.");
364 c.def(
"__eq__", _ArePtrsEqual<UnwrappedPtrType>,
365 "Equality operator: x == y");
366 c.def(
"__ne__", _ArePtrsNotEqual<UnwrappedPtrType>,
367 "Non-equality operator: x != y");
368 c.def(
"__lt__", _ArePtrsLessThan<UnwrappedPtrType>,
369 "Less than operator: x < y");
373 template <
typename CLS>
374 void visit(CLS &c)
const {
375 typedef typename CLS::wrapped_type Type;
376 typedef typename CLS::metadata::held_type_arg PtrType;
377 static_assert(TF_SUPPORTS_WEAKPTR(Type),
378 "Type must support TfWeakPtr.");
380 _RegisterConversions<PtrType>
381 ((Type *)0, detail::unwrap_wrapper((Type *)0));
384 Tf_RegisterPythonObjectFinder<Type, PtrType>();
387 _AddAPI<PtrType>(c, (Type *)0, detail::unwrap_wrapper((Type *)0));
391struct RefAndWeakPtr : def_visitor<RefAndWeakPtr> {
392 friend class def_visitor_access;
394 template <
typename CLS,
typename Wrapper,
typename T>
395 static void _AddAPI(Wrapper *, T *) {
396 _PtrFromPython<TfRefPtr<T> >();
398 _PtrInterface<typename CLS::metadata::held_type>::template
399 Rebind<T>::Type PtrType;
400 _ConvertPtrToPython<TfRefPtr<T>, PtrType>();
403 template <
typename CLS>
404 void visit(CLS &c)
const {
405 typedef typename CLS::wrapped_type Type;
406 static_assert(TF_SUPPORTS_REFPTR(Type),
407 "Type must support TfRefPtr.");
410 _AddAPI<CLS>((Type *)0, detail::unwrap_wrapper((Type *)0));
416struct TfPyWeakPtr : Tf_PyDefHelpers::WeakPtr {};
417struct TfPyRefAndWeakPtr : Tf_PyDefHelpers::RefAndWeakPtr {};
419PXR_NAMESPACE_CLOSE_SCOPE
Type independent WeakPtr holder class.
Low-level utilities for informing users of various internal and external diagnostic conditions.
Provides the ability to hold an arbitrary TfWeakPtr in a non-type-specific manner in order to observe...
Reference-counted smart pointer utility class.
Demangle C++ typenames generated by the typeid() facility.
std::string ArchGetDemangled()
Return demangled RTTI generated-type name.
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definitions of basic string utilities in tf.
A boost.python visitor that associates the Python class object created by the wrapping with the TfTyp...
Pointer storage with deletion detection.