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; }
155 template <
class PtrType>
156 struct _PtrFromPythonConversionPolicy {
157 static void Apply(PtrType
const &, PyObject *) { }
162 template <
typename T>
163 struct _PtrFromPythonConversionPolicy<
TfRefPtr<T> > {
164 static void Apply(
TfRefPtr<T> const &p, PyObject *obj) {
165 Tf_PyRemovePythonOwnership(p, obj);
170 struct _PtrFromPython {
171 typedef typename _PtrInterface<Ptr>::Pointee Pointee;
173 converter::registry::insert(&convertible, &construct,
177 static void *convertible(PyObject *p) {
180 void *result = converter::get_lvalue_from_python
181 (p, converter::registered<Pointee>::converters);
185 static void construct(PyObject* source, converter::
186 rvalue_from_python_stage1_data* data) {
187 void*
const storage = ((converter::rvalue_from_python_storage<Ptr>*)
188 data)->storage.bytes;
190 if (data->convertible == source)
193 Ptr ptr(static_cast<Pointee*>(data->convertible));
194 new (storage) Ptr(ptr);
195 _PtrFromPythonConversionPolicy<Ptr>::Apply(ptr, source);
198 Tf_PySetPythonIdentity(ptr, source);
200 data->convertible = storage;
207 template <
typename PtrType>
208 struct _AnyWeakPtrFromPython {
210 _AnyWeakPtrFromPython() {
211 converter::registry::insert(&convertible, &construct,
212 type_id<TfAnyWeakPtr>());
215 static void *convertible(PyObject *p) {
218 void *result = converter::get_lvalue_from_python
219 (p, converter::registered
220 <
typename _PtrInterface<PtrType>::Pointee>::converters);
224 static void construct(PyObject* source, converter::
225 rvalue_from_python_stage1_data* data) {
226 void*
const storage = ((converter::rvalue_from_python_storage
229 if (data->convertible == source)
232 typedef typename _PtrInterface<PtrType>::Pointee T;
233 T *ptr =
static_cast<T*
>(data->convertible);
234 PtrType smartPtr(ptr);
238 data->convertible = storage;
242 template <
typename Ptr>
243 struct _ConstPtrToPython {
244 typedef typename _PtrInterface<Ptr>::ConstPtr ConstPtr;
245 typedef typename _PtrInterface<Ptr>::NonConstPtr NonConstPtr;
246 _ConstPtrToPython() {
247 to_python_converter<ConstPtr, _ConstPtrToPython<Ptr> >();
249 static PyObject *convert(ConstPtr
const &p) {
250 return incref(
object(TfConst_cast<NonConstPtr>(p)).ptr());
254 template <
typename Ptr>
255 struct _PtrToPython {
257 to_python_converter<Ptr, _PtrToPython<Ptr> >();
259 static PyObject *convert(Ptr
const &p) {
260 std::pair<PyObject*, bool> ret = TfMakePyPtr<Ptr>::Execute(p);
262 Tf_PySetPythonIdentity(p, ret.first);
268 template <
typename SrcPtr,
typename DstPtr>
269 struct _ConvertPtrToPython {
270 _ConvertPtrToPython() {
271 to_python_converter<SrcPtr, _ConvertPtrToPython<SrcPtr, DstPtr> >();
273 static PyObject *convert(SrcPtr
const &p) {
275 return incref(
object(dst).ptr());
279 template <
typename Ptr>
280 struct _PtrToPythonWrapper {
285 static converter::to_python_function_t _originalConverter;
288 static PyObject *Convert(
void const *x) {
290 Ptr
const &p = *
static_cast<Ptr
const *
>(x);
292 std::pair<PyObject*, bool> ret = TfMakePyPtr<Ptr>::Execute(p);
293 if (ret.first == Py_None) {
295 Py_DECREF(ret.first);
296 ret.first = _originalConverter(x);
299 Tf_PySetPythonIdentity(p, ret.first);
304 template <
typename T>
305 converter::to_python_function_t
306 _PtrToPythonWrapper<T>::_originalConverter = 0;
308 struct WeakPtr : def_visitor<WeakPtr> {
309 friend class def_visitor_access;
311 template <
typename WrapperPtrType,
typename Wrapper,
typename T>
312 static void _RegisterConversions(Wrapper *, T *) {
313 _RegisterConversionsHelper<WrapperPtrType, Wrapper, T>();
316 template <
typename WrapperPtrType,
typename Wrapper,
typename T>
317 static void _RegisterConversionsHelper() {
319 static_assert(std::is_same<
320 typename _PtrInterface<WrapperPtrType>::Pointee,
322 "Pointee must be same type as Wrapper.");
325 _PtrInterface<WrapperPtrType>::template Rebind<T>::Type PtrType;
328 _PtrFromPython<PtrType>();
331 _AnyWeakPtrFromPython<PtrType>();
334 implicitly_convertible<PtrType,
335 typename _PtrInterface<PtrType>::ConstPtr >();
338 _ConstPtrToPython<PtrType>();
348 converter::registration *r =
const_cast<converter::registration *
>
349 (converter::registry::query(type_id<WrapperPtrType>()));
351 _PtrToPythonWrapper<WrapperPtrType>::
352 _originalConverter = r->m_to_python;
353 r->m_to_python = _PtrToPythonWrapper<WrapperPtrType>::Convert;
361 if (!std::is_same<Wrapper, T>::value)
362 _PtrToPython<PtrType>();
366 template <
typename PtrType,
typename CLS,
typename Wrapper,
typename T>
367 static void _AddAPI(CLS &c, Wrapper *, T *) {
369 _PtrInterface<PtrType>::template Rebind<T>::Type UnwrappedPtrType;
371 c.add_property(
"expired", _IsPtrExpired<UnwrappedPtrType>,
373 "True if this object has expired, False otherwise.");
374 c.def(TfPyBoolBuiltinFuncName, _IsPtrValid<UnwrappedPtrType>,
376 "True if this object has not expired. False otherwise.");
377 c.def(
"__eq__", _ArePtrsEqual<UnwrappedPtrType>,
378 "Equality operator: x == y");
379 c.def(
"__ne__", _ArePtrsNotEqual<UnwrappedPtrType>,
380 "Non-equality operator: x != y");
384 template <
typename CLS>
385 void visit(CLS &c)
const {
386 typedef typename CLS::wrapped_type Type;
387 typedef typename CLS::metadata::held_type_arg PtrType;
388 static_assert(TF_SUPPORTS_WEAKPTR(Type),
389 "Type must support TfWeakPtr.");
391 _RegisterConversions<PtrType>
392 ((Type *)0, detail::unwrap_wrapper((Type *)0));
395 Tf_RegisterPythonObjectFinder<Type, PtrType>();
398 _AddAPI<PtrType>(c, (Type *)0, detail::unwrap_wrapper((Type *)0));
402 struct RefAndWeakPtr : def_visitor<RefAndWeakPtr> {
403 friend class def_visitor_access;
405 template <
typename CLS,
typename Wrapper,
typename T>
406 static void _AddAPI(Wrapper *, T *) {
407 _PtrFromPython<TfRefPtr<T> >();
409 _PtrInterface<typename CLS::metadata::held_type>::template
410 Rebind<T>::Type PtrType;
411 _ConvertPtrToPython<TfRefPtr<T>, PtrType>();
414 template <
typename CLS>
415 void visit(CLS &c)
const {
416 typedef typename CLS::wrapped_type Type;
417 static_assert(TF_SUPPORTS_REFPTR(Type),
418 "Type must support TfRefPtr.");
421 _AddAPI<CLS>((Type *)0, detail::unwrap_wrapper((Type *)0));
427 struct TfPyWeakPtr : Tf_PyDefHelpers::WeakPtr {};
428 struct TfPyRefAndWeakPtr : Tf_PyDefHelpers::RefAndWeakPtr {};
430 PXR_NAMESPACE_CLOSE_SCOPE
432 #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.