25 #if !BOOST_PP_IS_ITERATING 27 #ifndef PXR_BASE_TF_MAKE_PY_CONSTRUCTOR_H 28 #define PXR_BASE_TF_MAKE_PY_CONSTRUCTOR_H 35 # define TF_MAX_ARITY 7 36 #endif // TF_MAX_ARITY 40 #include "pxr/base/tf/api.h" 44 #include "pxr/base/tf/pyError.h" 45 #include "pxr/base/tf/pyIdentity.h" 51 #include <boost/preprocessor/iterate.hpp> 52 #include <boost/preprocessor/punctuation/comma_if.hpp> 53 #include <boost/preprocessor/repetition/enum.hpp> 54 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 55 #include <boost/preprocessor/repetition/enum_params.hpp> 56 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> 57 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 58 #include <boost/preprocessor/repetition/repeat.hpp> 59 #include <boost/preprocessor/seq/for_each.hpp> 60 #include <boost/python/def_visitor.hpp> 61 #include <boost/python/dict.hpp> 62 #include <boost/python/errors.hpp> 63 #include <boost/python/list.hpp> 64 #include <boost/python/object/iterator.hpp> 65 #include <boost/python/raw_function.hpp> 66 #include <boost/python/tuple.hpp> 67 #include <boost/python/type_id.hpp> 68 #include <boost/type_traits/is_same.hpp> 69 #include <boost/type_traits/remove_reference.hpp> 73 PXR_NAMESPACE_OPEN_SCOPE
111 namespace Tf_MakePyConstructor {
113 namespace bp = boost::python;
115 template <
typename CTOR>
116 struct InitVisitor : bp::def_visitor<InitVisitor<CTOR> > {
117 friend class bp::def_visitor_access;
118 const std::string _doc;
119 InitVisitor(
const std::string &doc = std::string()) : _doc(doc) {}
121 template <
typename CLS>
122 void visit(CLS &c)
const {
123 c.def(
"__init__", CTOR::template init_callable<CLS>(), _doc.c_str());
126 template <
class CLS,
class Options>
127 void visit(CLS &c,
char const* name, Options& options)
const {
129 c.def(name, CTOR::template init_callable<CLS>(options), _doc.c_str());
135 bp::object _DummyInit(bp::tuple
const & ,
138 template <
typename CTOR>
139 struct NewVisitor : bp::def_visitor<NewVisitor<CTOR> > {
140 friend class bp::def_visitor_access;
141 const std::string _doc;
142 NewVisitor(
const std::string &doc = std::string()) : _doc(doc) {}
144 template <
typename CLS>
145 void visit(CLS &c)
const {
158 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
159 c.attr(
"__new__") = c.attr(
"__new__");
160 c.def(
"__new__", CTOR::template __new__<CLS>, _doc.c_str());
161 c.staticmethod(
"__new__");
164 c.def(
"__init__", bp::raw_function(_DummyInit));
167 template <
class CLS,
class Options>
168 void visit(CLS &c,
char const* name, Options& options)
const {
181 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
182 c.attr(
"__new__") = c.attr(
"__new__");
183 c.def(
"__new__", CTOR::template __new__<CLS>,
189 c.staticmethod(
"__new__");
192 c.def(
"__init__", bp::raw_function(_DummyInit));
198 typedef bp::object object;
200 template <
typename T>
201 struct InstallPolicy {
202 static void PostInstall(
object const &
self, T
const &t,
207 template <
typename T>
208 struct InstallPolicy<
TfRefPtr<T> > {
209 static_assert(Tf_SupportsUniqueChanged<T>::Value,
210 "Type T must support refcount unique changed notification.");
211 static void PostInstall(
object const &
self,
TfRefPtr<T> const &ptr,
212 const void *uniqueId) {
216 Tf_PyAddPythonOwnership(ptr, uniqueId,
self.ptr());
220 template <
typename CLS,
typename T>
221 void Install(
object const &
self, T
const &t,
TfErrorMark const &m) {
224 typedef typename CLS::metadata::holder Holder;
225 typedef typename bp::objects::instance<Holder> instance_t;
226 typedef InstallPolicy<T> Policy;
227 typedef typename CLS::metadata::held_type HeldType;
230 void *memory = Holder::
232 allocate(
self.ptr(), offsetof(instance_t, storage),
sizeof(Holder));
235 Holder *holder = (
new (memory) Holder(held));
237 if (TfPyConvertTfErrorsToPythonException(m))
238 bp::throw_error_already_set();
244 bp::detail::initialize_wrapper(
self.ptr(), &(*(held.operator->())));
245 holder->install(
self.ptr());
248 Tf_PySetPythonIdentity(held,
self.ptr());
250 Policy::PostInstall(
self, t, held.GetUniqueIdentifier());
253 Holder::deallocate(
self.ptr(), memory);
throw;
259 template <
typename WeakPtr,
typename P>
260 struct _RefPtrFactoryConverter {
261 typedef typename boost::remove_reference<P>::type Ptr;
262 bool convertible()
const {
269 PyObject *operator()(Ptr
const &p)
const {
270 typedef InstallPolicy<Ptr> Policy;
271 WeakPtr ptr(static_cast<typename WeakPtr::DataType *>
276 return bp::incref(Py_None);
281 Policy::PostInstall(result, p, ptr.GetUniqueIdentifier());
282 return bp::incref(result.ptr());
286 PyTypeObject
const *get_pytype()
const {
287 return boost::python::objects::registered_class_object(
288 boost::python::type_id<typename WeakPtr::DataType>()).get();
292 template <
typename WeakPtr =
void>
293 struct RefPtrFactory {
294 template <
typename FactoryResultPtr>
296 typedef typename boost::mpl::if_<boost::is_same<WeakPtr, void>,
298 WeakPtr>::type WeakPtrType;
299 typedef _RefPtrFactoryConverter<WeakPtrType, FactoryResultPtr> type;
303 template <
typename SIG>
307 static void SetFunc(Sig *func) {
313 "Duplicate will be ignored.",
320 template <
typename SIG> SIG *CtorBase<SIG>::_func = 0;
324 template <
typename SIG>
struct InitCtor;
325 template <
typename SIG>
struct InitCtorWithBackReference;
326 template <
typename SIG>
struct InitCtorWithVarArgs;
327 template <
typename SIG>
struct NewCtor;
328 template <
typename SIG>
struct NewCtorWithClassReference;
329 #define BOOST_PP_ITERATION_LIMITS (0, TF_MAX_ARITY) 330 #define BOOST_PP_FILENAME_1 "pxr/base/tf/makePyConstructor.h" 331 #include BOOST_PP_ITERATE() 339 template <
typename T>
340 Tf_MakePyConstructor::InitVisitor
341 <
typename Tf_MakePyConstructor::InitCtor<T> >
342 TfMakePyConstructor(T *func,
const std::string &doc = std::string()) {
344 Tf_MakePyConstructor::InitCtor<T> Ctor(func);
345 return Tf_MakePyConstructor::InitVisitor
346 <Tf_MakePyConstructor::InitCtor<T> >(doc);
349 template <
typename T>
350 Tf_MakePyConstructor::InitVisitor
351 <
typename Tf_MakePyConstructor::InitCtorWithBackReference<T> >
352 TfMakePyConstructorWithBackReference(T *func,
const std::string &doc = std::string()) {
354 Tf_MakePyConstructor::InitCtorWithBackReference<T> Ctor(func);
355 return Tf_MakePyConstructor::InitVisitor
356 <Tf_MakePyConstructor::InitCtorWithBackReference<T> >(doc);
359 template <
typename T>
360 Tf_MakePyConstructor::InitVisitor
361 <
typename Tf_MakePyConstructor::InitCtorWithVarArgs<T> >
362 TfMakePyConstructorWithVarArgs(T *func,
const std::string &doc = std::string()) {
364 Tf_MakePyConstructor::InitCtorWithVarArgs<T> Ctor(func);
365 return Tf_MakePyConstructor::InitVisitor
366 <Tf_MakePyConstructor::InitCtorWithVarArgs<T> >(doc);
369 template <
typename T>
370 Tf_MakePyConstructor::NewVisitor
371 <
typename Tf_MakePyConstructor::NewCtor<T> >
372 TfMakePyNew(T *func,
const std::string &doc = std::string()) {
374 Tf_MakePyConstructor::NewCtor<T> Ctor(func);
375 return Tf_MakePyConstructor::NewVisitor
376 <Tf_MakePyConstructor::NewCtor<T> >(doc);
379 template <
typename T>
380 Tf_MakePyConstructor::NewVisitor
381 <
typename Tf_MakePyConstructor::NewCtorWithClassReference<T> >
382 TfMakePyNewWithClassReference(T *func,
const std::string &doc = std::string()) {
384 Tf_MakePyConstructor::NewCtorWithClassReference<T> Ctor(func);
385 return Tf_MakePyConstructor::NewVisitor
386 <Tf_MakePyConstructor::NewCtorWithClassReference<T> >(doc);
390 template <
typename T =
void>
391 struct TfPyRefPtrFactory :
public Tf_MakePyConstructor::RefPtrFactory<T> {};
393 template <
typename T>
struct Tf_PySequenceToListConverterRefPtrFactory;
398 template <
typename T>
400 typedef Tf_PySequenceToListConverterRefPtrFactory<T> type;
405 template <
typename T>
406 struct Tf_PySequenceToListConverterRefPtrFactory {
407 typedef typename boost::remove_reference<T>::type SeqType;
408 bool convertible()
const {
411 PyObject *operator()(T seq)
const {
412 using namespace boost::python;
414 typedef typename Tf_MakePyConstructor::RefPtrFactory<>::
415 apply<typename SeqType::value_type>::type RefPtrFactory;
417 boost::python::list l;
418 for (
typename SeqType::const_iterator i = seq.begin();
419 i != seq.end(); ++i) {
420 l.append(
object(handle<>(RefPtrFactory()(*i))));
422 return boost::python::incref(l.ptr());
426 PyTypeObject
const *get_pytype()
const {
431 PXR_NAMESPACE_CLOSE_SCOPE
433 #endif // PXR_BASE_TF_MAKE_PY_CONSTRUCTOR_H 435 #else // BOOST_PP_IS_ITERATING 437 #define N BOOST_PP_ITERATION() 439 #define SIGNATURE R (BOOST_PP_ENUM_PARAMS(N, A)) 440 #define PARAMLIST BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, a) 441 #define ARGLIST BOOST_PP_ENUM_PARAMS(N, a) 447 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
448 struct InitCtor<SIGNATURE> : CtorBase<SIGNATURE> {
449 typedef CtorBase<SIGNATURE> Base;
450 typedef typename Base::Sig Sig;
451 InitCtor(Sig *func) { Base::SetFunc(func); }
453 template <
typename CLS>
454 static bp::object init_callable() {
455 return bp::make_function(__init__<CLS>);
458 template <
typename CLS,
typename Options>
459 static bp::object init_callable(Options& o) {
460 return bp::make_function(__init__<CLS>, o.policies(), o.keywords()) ;
463 template <
typename CLS>
464 static void __init__(
object &
self PARAMLIST) {
466 Install<CLS>(
self, Base::_func(ARGLIST), m);
470 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
471 struct NewCtor<SIGNATURE> : CtorBase<SIGNATURE> {
472 typedef CtorBase<SIGNATURE> Base;
473 typedef typename Base::Sig Sig;
474 NewCtor(Sig *func) { Base::SetFunc(func); }
477 static bp::object __new__(
object &cls PARAMLIST) {
478 typedef typename CLS::metadata::held_type HeldType;
480 R r((Base::_func(ARGLIST)));
482 if (TfPyConvertTfErrorsToPythonException(m))
483 bp::throw_error_already_set();
489 bp::detail::initialize_wrapper(ret.ptr(), get_pointer(h));
491 bp::setattr(ret,
"__class__", cls);
493 InstallPolicy<R>::PostInstall(ret, r, h.GetUniqueIdentifier());
498 #define VAR_SIGNATURE \ 499 R (BOOST_PP_ENUM_PARAMS(N, A) BOOST_PP_COMMA_IF(N) \ 500 const bp::tuple&, const bp::dict&) 502 #define FORMAT_STR(z, n, data) "%s, " 503 #define ARG_TYPE_STR_A(z, n, data) bp::type_id<A##n>().name() 505 #define EXTRACT_REQ_ARG_A(z, n, data) \ 508 bp::extract<typename boost::remove_reference<A##n>::type>(data[n + 1]) 510 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
511 struct InitCtorWithVarArgs<VAR_SIGNATURE> : CtorBase<VAR_SIGNATURE> {
512 typedef CtorBase<VAR_SIGNATURE> Base;
513 typedef typename Base::Sig Sig;
514 InitCtorWithVarArgs(Sig *func) { Base::SetFunc(func); }
516 template <
typename CLS>
517 static bp::object init_callable() {
521 return bp::raw_function(__init__<CLS>, 1);
524 template <
typename CLS,
typename Options>
525 static bp::object init_callable(Options& options) {
528 return bp::raw_function(
529 bp::make_function(__init__<CLS>, options.policies()),
533 template <
typename CLS>
534 static bp::object __init__(
const bp::tuple& args,
const bp::dict& kwargs) {
537 const unsigned int numArgs = bp::len(args);
538 if (numArgs - 1 < N) {
543 "Arguments to __init__ did not match C++ signature:\n" 544 "\t__init__(" BOOST_PP_REPEAT(N, FORMAT_STR, 0)
"...)" 545 BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM(N, ARG_TYPE_STR_A, 0)
558 BOOST_PP_ENUM(N, EXTRACT_REQ_ARG_A, args) BOOST_PP_COMMA_IF(N)
559 bp::tuple(args.slice(N + 1, numArgs)), kwargs),
569 #define PARAMLIST BOOST_PP_ENUM_BINARY_PARAMS(N, A, a) 577 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
578 struct InitCtorWithBackReference<SIGNATURE> : CtorBase<SIGNATURE> {
579 typedef CtorBase<SIGNATURE> Base;
580 typedef typename Base::Sig Sig;
581 InitCtorWithBackReference(Sig *func) { Base::SetFunc(func); }
583 template <
typename CLS>
584 static bp::object init_callable() {
585 return bp::make_function(__init__<CLS>);
588 template <
typename CLS,
typename Options>
589 static bp::object init_callable(Options& o) {
590 return bp::make_function(__init__<CLS>, o.policies(), o.keywords());
593 template <
typename CLS>
594 static void __init__(PARAMLIST) {
596 Install<CLS>(a0, Base::_func(ARGLIST), m);
600 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
601 struct NewCtorWithClassReference<SIGNATURE> : CtorBase<SIGNATURE> {
602 typedef CtorBase<SIGNATURE> Base;
603 typedef typename Base::Sig Sig;
604 NewCtorWithClassReference(Sig *func) { Base::SetFunc(func); }
607 static bp::object __new__(PARAMLIST) {
608 typedef typename CLS::metadata::held_type HeldType;
610 R r(Base::_func(ARGLIST));
612 if (TfPyConvertTfErrorsToPythonException(m))
613 bp::throw_error_already_set();
619 bp::detail::initialize_wrapper(ret.ptr(), get_pointer(h));
621 bp::setattr(ret,
"__class__", a0);
623 InstallPolicy<R>::PostInstall(ret, r, h.GetUniqueIdentifier());
636 #undef ARG_TYPE_STR_A 637 #undef EXTRACT_REQ_ARG_A 639 #endif // BOOST_PP_IS_ITERATING TF_API std::string TfStringPrintf(const char *fmt,...)
Returns a string formed by a printf()-like specification.
A boost::python result converter generator which converts standard library sequences to lists of pyth...
#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.
Definitions of basic string utilities in tf.
Low-level utilities for informing users of various internal and external diagnostic conditions.
boost::python::object TfPyObject(T const &t, bool complainOnFailure=true)
Return a python object for the given C++ object, loading the appropriate wrapper code if necessary.
Miscellaneous Utilities for dealing with script.
Pointer storage with deletion detection.
Demangle C++ typenames generated by the typeid() facility.
Pointer storage with deletion detection.
Class used to record the end of the error-list.
TF_API bool TfPyIsNone(boost::python::object const &obj)
Return true iff obj is None.
TF_API void TfPyThrowTypeError(std::string const &msg)
Raises a python TypeError and throws a C++ exception.
Reference-counted smart pointer utility class.
TF_API void TfPyThrowRuntimeError(std::string const &msg)
Raises a python RuntimError and throws a C++ exception.