24 #ifndef PXR_BASE_TF_PY_PTR_HELPERS_H 25 #define PXR_BASE_TF_PY_PTR_HELPERS_H 32 #include "pxr/base/tf/pyIdentity.h" 33 #include "pxr/base/tf/pyObjectFinder.h" 34 #include "pxr/base/tf/wrapTypeHelpers.h" 43 #include <boost/python/class.hpp> 44 #include <boost/python/converter/from_python.hpp> 45 #include <boost/python/converter/registered.hpp> 46 #include <boost/python/converter/registrations.hpp> 47 #include <boost/python/converter/registry.hpp> 48 #include <boost/python/converter/rvalue_from_python_data.hpp> 49 #include <boost/python/converter/to_python_function_type.hpp> 50 #include <boost/python/def_visitor.hpp> 51 #include <boost/python/handle.hpp> 52 #include <boost/python/implicit.hpp> 53 #include <boost/python/to_python_converter.hpp> 57 PXR_NAMESPACE_OPEN_SCOPE
76 template <
typename Ptr>
78 typedef typename Ptr::DataType Pointee;
79 typedef boost::python::objects::pointer_holder<Ptr, Pointee> Holder;
80 typedef std::pair<PyObject*, bool> Result;
85 static Result Execute(Ptr
const& p)
88 if (!p.GetUniqueIdentifier())
89 return Result(boost::python::detail::none(),
false);
97 if (PyObject *
id = Tf_PyGetPythonIdentity(p))
98 return Result(
id,
false);
102 PyObject *res = boost::python::objects::make_ptr_instance
103 <Pointee, Holder>::execute(p);
106 return Result(res, res != Py_None);
110 namespace Tf_PyDefHelpers {
112 using namespace boost::python;
114 template <
typename Ptr>
115 struct _PtrInterface {
116 typedef typename Ptr::DataType Pointee;
117 typedef typename boost::add_const<Pointee>::type ConstPointee;
118 typedef typename boost::remove_const<Pointee>::type NonConstPointee;
120 template <
typename U>
122 typedef typename Ptr::template Rebind<U>::Type Type;
125 typedef typename Rebind<ConstPointee>::Type ConstPtr;
126 typedef typename Rebind<NonConstPointee>::Type NonConstPtr;
130 template <
typename PtrType>
131 bool _IsPtrExpired(
object const &
self) {
133 PtrType p = extract<PtrType>(
self);
135 }
catch (boost::python::error_already_set
const &) {
141 template <
typename PtrType>
142 bool _IsPtrValid(
object const &
self) {
143 return !_IsPtrExpired<PtrType>(
self);
146 template <
typename PtrType>
147 bool _ArePtrsEqual(PtrType
const &
self,
148 PtrType
const &other) {
return self == other; }
149 template <
typename PtrType>
150 bool _ArePtrsNotEqual(PtrType
const &
self,
151 PtrType
const &other) {
return self != other; }
152 template <
typename PtrType>
153 bool _ArePtrsLessThan(PtrType
const &
self,
154 PtrType
const &other) {
return self < other; }
158 template <
class PtrType>
159 struct _PtrFromPythonConversionPolicy {
160 static void Apply(PtrType
const &, PyObject *) { }
165 template <
typename T>
166 struct _PtrFromPythonConversionPolicy<
TfRefPtr<T> > {
167 static void Apply(
TfRefPtr<T> const &p, PyObject *obj) {
168 Tf_PyRemovePythonOwnership(p, obj);
173 struct _PtrFromPython {
174 typedef typename _PtrInterface<Ptr>::Pointee Pointee;
176 converter::registry::insert(&convertible, &construct,
180 static void *convertible(PyObject *p) {
183 void *result = converter::get_lvalue_from_python
184 (p, converter::registered<Pointee>::converters);
188 static void construct(PyObject* source, converter::
189 rvalue_from_python_stage1_data* data) {
190 void*
const storage = ((converter::rvalue_from_python_storage<Ptr>*)
191 data)->storage.bytes;
193 if (data->convertible == source)
196 Ptr ptr(static_cast<Pointee*>(data->convertible));
197 new (storage) Ptr(ptr);
198 _PtrFromPythonConversionPolicy<Ptr>::Apply(ptr, source);
201 Tf_PySetPythonIdentity(ptr, source);
203 data->convertible = storage;
210 template <
typename PtrType>
211 struct _AnyWeakPtrFromPython {
213 _AnyWeakPtrFromPython() {
214 converter::registry::insert(&convertible, &construct,
215 type_id<TfAnyWeakPtr>());
218 static void *convertible(PyObject *p) {
221 void *result = converter::get_lvalue_from_python
222 (p, converter::registered
223 <
typename _PtrInterface<PtrType>::Pointee>::converters);
227 static void construct(PyObject* source, converter::
228 rvalue_from_python_stage1_data* data) {
229 void*
const storage = ((converter::rvalue_from_python_storage
232 if (data->convertible == source)
235 typedef typename _PtrInterface<PtrType>::Pointee T;
236 T *ptr = static_cast<T*>(data->convertible);
237 PtrType smartPtr(ptr);
241 data->convertible = storage;
245 template <
typename Ptr>
246 struct _ConstPtrToPython {
247 typedef typename _PtrInterface<Ptr>::ConstPtr ConstPtr;
248 typedef typename _PtrInterface<Ptr>::NonConstPtr NonConstPtr;
249 _ConstPtrToPython() {
250 to_python_converter<ConstPtr, _ConstPtrToPython<Ptr> >();
252 static PyObject *convert(ConstPtr
const &p) {
253 return incref(
object(TfConst_cast<NonConstPtr>(p)).ptr());
257 template <
typename Ptr>
258 struct _PtrToPython {
260 to_python_converter<Ptr, _PtrToPython<Ptr> >();
262 static PyObject *convert(Ptr
const &p) {
263 std::pair<PyObject*, bool> ret = TfMakePyPtr<Ptr>::Execute(p);
265 Tf_PySetPythonIdentity(p, ret.first);
271 template <
typename SrcPtr,
typename DstPtr>
272 struct _ConvertPtrToPython {
273 _ConvertPtrToPython() {
274 to_python_converter<SrcPtr, _ConvertPtrToPython<SrcPtr, DstPtr> >();
276 static PyObject *convert(SrcPtr
const &p) {
278 return incref(
object(dst).ptr());
282 template <
typename Ptr>
283 struct _PtrToPythonWrapper {
288 static converter::to_python_function_t _originalConverter;
291 static PyObject *Convert(
void const *x) {
293 Ptr
const &p = *static_cast<Ptr const *>(x);
295 std::pair<PyObject*, bool> ret = TfMakePyPtr<Ptr>::Execute(p);
296 if (ret.first == Py_None) {
298 Py_DECREF(ret.first);
299 ret.first = _originalConverter(x);
302 Tf_PySetPythonIdentity(p, ret.first);
307 template <
typename T>
308 converter::to_python_function_t
309 _PtrToPythonWrapper<T>::_originalConverter = 0;
311 struct WeakPtr : def_visitor<WeakPtr> {
312 friend class def_visitor_access;
314 template <
typename WrapperPtrType,
typename Wrapper,
typename T>
315 static void _RegisterConversions(Wrapper *, T *) {
316 _RegisterConversionsHelper<WrapperPtrType, Wrapper, T>();
319 template <
typename WrapperPtrType,
typename Wrapper,
typename T>
320 static void _RegisterConversionsHelper() {
322 static_assert(std::is_same<
323 typename _PtrInterface<WrapperPtrType>::Pointee,
325 "Pointee must be same type as Wrapper.");
328 _PtrInterface<WrapperPtrType>::template Rebind<T>::Type PtrType;
331 _PtrFromPython<PtrType>();
334 _AnyWeakPtrFromPython<PtrType>();
337 implicitly_convertible<PtrType,
338 typename _PtrInterface<PtrType>::ConstPtr >();
341 _ConstPtrToPython<PtrType>();
351 converter::registration *r = const_cast<converter::registration *>
352 (converter::registry::query(type_id<WrapperPtrType>()));
354 _PtrToPythonWrapper<WrapperPtrType>::
355 _originalConverter = r->m_to_python;
356 r->m_to_python = _PtrToPythonWrapper<WrapperPtrType>::Convert;
364 if (!std::is_same<Wrapper, T>::value)
365 _PtrToPython<PtrType>();
369 template <
typename PtrType,
typename CLS,
typename Wrapper,
typename T>
370 static void _AddAPI(CLS &c, Wrapper *, T *) {
372 _PtrInterface<PtrType>::template Rebind<T>::Type UnwrappedPtrType;
374 c.add_property(
"expired", _IsPtrExpired<UnwrappedPtrType>,
376 "True if this object has expired, False otherwise.");
377 c.def(
"__bool__", _IsPtrValid<UnwrappedPtrType>,
379 "True if this object has not expired. False otherwise.");
380 c.def(
"__eq__", _ArePtrsEqual<UnwrappedPtrType>,
381 "Equality operator: x == y");
382 c.def(
"__ne__", _ArePtrsNotEqual<UnwrappedPtrType>,
383 "Non-equality operator: x != y");
384 c.def(
"__lt__", _ArePtrsLessThan<UnwrappedPtrType>,
385 "Less than operator: x < y");
389 template <
typename CLS>
390 void visit(CLS &c)
const {
391 typedef typename CLS::wrapped_type Type;
392 typedef typename CLS::metadata::held_type_arg PtrType;
393 static_assert(TF_SUPPORTS_WEAKPTR(Type),
394 "Type must support TfWeakPtr.");
396 _RegisterConversions<PtrType>
397 ((Type *)0, detail::unwrap_wrapper((Type *)0));
400 Tf_RegisterPythonObjectFinder<Type, PtrType>();
403 _AddAPI<PtrType>(c, (Type *)0, detail::unwrap_wrapper((Type *)0));
407 struct RefAndWeakPtr : def_visitor<RefAndWeakPtr> {
408 friend class def_visitor_access;
410 template <
typename CLS,
typename Wrapper,
typename T>
411 static void _AddAPI(Wrapper *, T *) {
412 _PtrFromPython<TfRefPtr<T> >();
414 _PtrInterface<typename CLS::metadata::held_type>::template
415 Rebind<T>::Type PtrType;
416 _ConvertPtrToPython<TfRefPtr<T>, PtrType>();
419 template <
typename CLS>
420 void visit(CLS &c)
const {
421 typedef typename CLS::wrapped_type Type;
422 static_assert(TF_SUPPORTS_REFPTR(Type),
423 "Type must support TfRefPtr.");
426 _AddAPI<CLS>((Type *)0, detail::unwrap_wrapper((Type *)0));
432 struct TfPyWeakPtr : Tf_PyDefHelpers::WeakPtr {};
433 struct TfPyRefAndWeakPtr : Tf_PyDefHelpers::RefAndWeakPtr {};
435 PXR_NAMESPACE_CLOSE_SCOPE
437 #endif // PXR_BASE_TF_PY_PTR_HELPERS_H 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.