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> 71 PXR_NAMESPACE_OPEN_SCOPE
109 namespace Tf_MakePyConstructor {
111 namespace bp = boost::python;
113 template <
typename CTOR>
114 struct InitVisitor : bp::def_visitor<InitVisitor<CTOR> > {
115 friend class bp::def_visitor_access;
116 const std::string _doc;
117 InitVisitor(
const std::string &doc = std::string()) : _doc(doc) {}
119 template <
typename CLS>
120 void visit(CLS &c)
const {
121 c.def(
"__init__", CTOR::template init_callable<CLS>(), _doc.c_str());
124 template <
class CLS,
class Options>
125 void visit(CLS &c,
char const* name, Options& options)
const {
127 c.def(name, CTOR::template init_callable<CLS>(options), _doc.c_str());
133 bp::object _DummyInit(bp::tuple
const & ,
136 template <
typename CTOR>
137 struct NewVisitor : bp::def_visitor<NewVisitor<CTOR> > {
138 friend class bp::def_visitor_access;
139 const std::string _doc;
140 NewVisitor(
const std::string &doc = std::string()) : _doc(doc) {}
142 template <
typename CLS>
143 void visit(CLS &c)
const {
156 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
157 c.attr(
"__new__") = c.attr(
"__new__");
158 c.def(
"__new__", CTOR::template __new__<CLS>, _doc.c_str());
159 c.staticmethod(
"__new__");
162 c.def(
"__init__", bp::raw_function(_DummyInit));
165 template <
class CLS,
class Options>
166 void visit(CLS &c,
char const* name, Options& options)
const {
179 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
180 c.attr(
"__new__") = c.attr(
"__new__");
181 c.def(
"__new__", CTOR::template __new__<CLS>,
187 c.staticmethod(
"__new__");
190 c.def(
"__init__", bp::raw_function(_DummyInit));
196 typedef bp::object object;
198 template <
typename T>
199 struct InstallPolicy {
200 static void PostInstall(
object const &
self, T
const &t,
205 template <
typename T>
206 struct InstallPolicy<
TfRefPtr<T> > {
207 static_assert(Tf_SupportsUniqueChanged<T>::Value,
208 "Type T must support refcount unique changed notification.");
209 static void PostInstall(
object const &
self,
TfRefPtr<T> const &ptr,
210 const void *uniqueId) {
214 Tf_PyAddPythonOwnership(ptr, uniqueId,
self.ptr());
218 template <
typename CLS,
typename T>
219 void Install(
object const &
self, T
const &t,
TfErrorMark const &m) {
222 typedef typename CLS::metadata::holder Holder;
223 typedef typename bp::objects::instance<Holder> instance_t;
224 typedef InstallPolicy<T> Policy;
225 typedef typename CLS::metadata::held_type HeldType;
228 void *memory = Holder::
230 allocate(
self.ptr(), offsetof(instance_t, storage),
sizeof(Holder));
233 Holder *holder = (
new (memory) Holder(held));
235 if (TfPyConvertTfErrorsToPythonException(m))
236 bp::throw_error_already_set();
242 bp::detail::initialize_wrapper(
self.ptr(), &(*(held.operator->())));
243 holder->install(
self.ptr());
246 Tf_PySetPythonIdentity(held,
self.ptr());
248 Policy::PostInstall(
self, t, held.GetUniqueIdentifier());
251 Holder::deallocate(
self.ptr(), memory);
throw;
257 template <
typename WeakPtr,
typename P>
258 struct _RefPtrFactoryConverter {
259 typedef std::remove_reference_t<P> Ptr;
260 bool convertible()
const {
267 PyObject *operator()(Ptr
const &p)
const {
268 typedef InstallPolicy<Ptr> Policy;
269 WeakPtr ptr(static_cast<typename WeakPtr::DataType *>
274 return bp::incref(Py_None);
279 Policy::PostInstall(result, p, ptr.GetUniqueIdentifier());
280 return bp::incref(result.ptr());
284 PyTypeObject
const *get_pytype()
const {
285 return boost::python::objects::registered_class_object(
286 boost::python::type_id<typename WeakPtr::DataType>()).get();
290 template <
typename WeakPtr =
void>
291 struct RefPtrFactory {
292 template <
typename FactoryResultPtr>
294 using WeakPtrType = std::conditional_t<
295 std::is_same<WeakPtr, void>::value,
298 typedef _RefPtrFactoryConverter<WeakPtrType, FactoryResultPtr> type;
302 template <
typename SIG>
306 static void SetFunc(Sig *func) {
312 "Duplicate will be ignored.",
319 template <
typename SIG> SIG *CtorBase<SIG>::_func = 0;
323 template <
typename SIG>
struct InitCtor;
324 template <
typename SIG>
struct InitCtorWithBackReference;
325 template <
typename SIG>
struct InitCtorWithVarArgs;
326 template <
typename SIG>
struct NewCtor;
327 template <
typename SIG>
struct NewCtorWithClassReference;
328 #define BOOST_PP_ITERATION_LIMITS (0, TF_MAX_ARITY) 329 #define BOOST_PP_FILENAME_1 "pxr/base/tf/makePyConstructor.h" 330 #include BOOST_PP_ITERATE() 338 template <
typename T>
339 Tf_MakePyConstructor::InitVisitor
340 <
typename Tf_MakePyConstructor::InitCtor<T> >
341 TfMakePyConstructor(T *func,
const std::string &doc = std::string()) {
343 Tf_MakePyConstructor::InitCtor<T> Ctor(func);
344 return Tf_MakePyConstructor::InitVisitor
345 <Tf_MakePyConstructor::InitCtor<T> >(doc);
348 template <
typename T>
349 Tf_MakePyConstructor::InitVisitor
350 <
typename Tf_MakePyConstructor::InitCtorWithBackReference<T> >
351 TfMakePyConstructorWithBackReference(T *func,
const std::string &doc = std::string()) {
353 Tf_MakePyConstructor::InitCtorWithBackReference<T> Ctor(func);
354 return Tf_MakePyConstructor::InitVisitor
355 <Tf_MakePyConstructor::InitCtorWithBackReference<T> >(doc);
358 template <
typename T>
359 Tf_MakePyConstructor::InitVisitor
360 <
typename Tf_MakePyConstructor::InitCtorWithVarArgs<T> >
361 TfMakePyConstructorWithVarArgs(T *func,
const std::string &doc = std::string()) {
363 Tf_MakePyConstructor::InitCtorWithVarArgs<T> Ctor(func);
364 return Tf_MakePyConstructor::InitVisitor
365 <Tf_MakePyConstructor::InitCtorWithVarArgs<T> >(doc);
368 template <
typename T>
369 Tf_MakePyConstructor::NewVisitor
370 <
typename Tf_MakePyConstructor::NewCtor<T> >
371 TfMakePyNew(T *func,
const std::string &doc = std::string()) {
373 Tf_MakePyConstructor::NewCtor<T> Ctor(func);
374 return Tf_MakePyConstructor::NewVisitor
375 <Tf_MakePyConstructor::NewCtor<T> >(doc);
378 template <
typename T>
379 Tf_MakePyConstructor::NewVisitor
380 <
typename Tf_MakePyConstructor::NewCtorWithClassReference<T> >
381 TfMakePyNewWithClassReference(T *func,
const std::string &doc = std::string()) {
383 Tf_MakePyConstructor::NewCtorWithClassReference<T> Ctor(func);
384 return Tf_MakePyConstructor::NewVisitor
385 <Tf_MakePyConstructor::NewCtorWithClassReference<T> >(doc);
389 template <
typename T =
void>
390 struct TfPyRefPtrFactory :
public Tf_MakePyConstructor::RefPtrFactory<T> {};
392 template <
typename T>
struct Tf_PySequenceToListConverterRefPtrFactory;
397 template <
typename T>
399 typedef Tf_PySequenceToListConverterRefPtrFactory<T> type;
404 template <
typename T>
405 struct Tf_PySequenceToListConverterRefPtrFactory {
406 typedef std::remove_reference_t<T> SeqType;
407 bool convertible()
const {
410 PyObject *operator()(T seq)
const {
411 using namespace boost::python;
413 typedef typename Tf_MakePyConstructor::RefPtrFactory<>::
414 apply<typename SeqType::value_type>::type RefPtrFactory;
416 boost::python::list l;
417 for (
typename SeqType::const_iterator i = seq.begin();
418 i != seq.end(); ++i) {
419 l.append(
object(handle<>(RefPtrFactory()(*i))));
421 return boost::python::incref(l.ptr());
425 PyTypeObject
const *get_pytype()
const {
430 PXR_NAMESPACE_CLOSE_SCOPE
432 #endif // PXR_BASE_TF_MAKE_PY_CONSTRUCTOR_H 434 #else // BOOST_PP_IS_ITERATING 436 #define N BOOST_PP_ITERATION() 438 #define SIGNATURE R (BOOST_PP_ENUM_PARAMS(N, A)) 439 #define PARAMLIST BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, a) 440 #define ARGLIST BOOST_PP_ENUM_PARAMS(N, a) 446 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
447 struct InitCtor<SIGNATURE> : CtorBase<SIGNATURE> {
448 typedef CtorBase<SIGNATURE> Base;
449 typedef typename Base::Sig Sig;
450 InitCtor(Sig *func) { Base::SetFunc(func); }
452 template <
typename CLS>
453 static bp::object init_callable() {
454 return bp::make_function(__init__<CLS>);
457 template <
typename CLS,
typename Options>
458 static bp::object init_callable(Options& o) {
459 return bp::make_function(__init__<CLS>, o.policies(), o.keywords()) ;
462 template <
typename CLS>
463 static void __init__(
object &
self PARAMLIST) {
465 Install<CLS>(
self, Base::_func(ARGLIST), m);
469 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
470 struct NewCtor<SIGNATURE> : CtorBase<SIGNATURE> {
471 typedef CtorBase<SIGNATURE> Base;
472 typedef typename Base::Sig Sig;
473 NewCtor(Sig *func) { Base::SetFunc(func); }
476 static bp::object __new__(
object &cls PARAMLIST) {
477 typedef typename CLS::metadata::held_type HeldType;
479 R r((Base::_func(ARGLIST)));
481 if (TfPyConvertTfErrorsToPythonException(m))
482 bp::throw_error_already_set();
488 bp::detail::initialize_wrapper(ret.ptr(), get_pointer(h));
490 bp::setattr(ret,
"__class__", cls);
492 InstallPolicy<R>::PostInstall(ret, r, h.GetUniqueIdentifier());
497 #define VAR_SIGNATURE \ 498 R (BOOST_PP_ENUM_PARAMS(N, A) BOOST_PP_COMMA_IF(N) \ 499 const bp::tuple&, const bp::dict&) 501 #define FORMAT_STR(z, n, data) "%s, " 502 #define ARG_TYPE_STR_A(z, n, data) bp::type_id<A##n>().name() 504 #define EXTRACT_REQ_ARG_A(z, n, data) \ 507 bp::extract<typename std::remove_reference_t<A##n>>(data[n + 1]) 509 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
510 struct InitCtorWithVarArgs<VAR_SIGNATURE> : CtorBase<VAR_SIGNATURE> {
511 typedef CtorBase<VAR_SIGNATURE> Base;
512 typedef typename Base::Sig Sig;
513 InitCtorWithVarArgs(Sig *func) { Base::SetFunc(func); }
515 template <
typename CLS>
516 static bp::object init_callable() {
520 return bp::raw_function(__init__<CLS>, 1);
523 template <
typename CLS,
typename Options>
524 static bp::object init_callable(Options& options) {
527 return bp::raw_function(
528 bp::make_function(__init__<CLS>, options.policies()),
532 template <
typename CLS>
533 static bp::object __init__(
const bp::tuple& args,
const bp::dict& kwargs) {
536 const unsigned int numArgs = bp::len(args);
537 if (numArgs - 1 < N) {
542 "Arguments to __init__ did not match C++ signature:\n" 543 "\t__init__(" BOOST_PP_REPEAT(N, FORMAT_STR, 0)
"...)" 544 BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM(N, ARG_TYPE_STR_A, 0)
557 BOOST_PP_ENUM(N, EXTRACT_REQ_ARG_A, args) BOOST_PP_COMMA_IF(N)
558 bp::tuple(args.slice(N + 1, numArgs)), kwargs),
568 #define PARAMLIST BOOST_PP_ENUM_BINARY_PARAMS(N, A, a) 576 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
577 struct InitCtorWithBackReference<SIGNATURE> : CtorBase<SIGNATURE> {
578 typedef CtorBase<SIGNATURE> Base;
579 typedef typename Base::Sig Sig;
580 InitCtorWithBackReference(Sig *func) { Base::SetFunc(func); }
582 template <
typename CLS>
583 static bp::object init_callable() {
584 return bp::make_function(__init__<CLS>);
587 template <
typename CLS,
typename Options>
588 static bp::object init_callable(Options& o) {
589 return bp::make_function(__init__<CLS>, o.policies(), o.keywords());
592 template <
typename CLS>
593 static void __init__(PARAMLIST) {
595 Install<CLS>(a0, Base::_func(ARGLIST), m);
599 template <
typename R BOOST_PP_ENUM_TRAILING_PARAMS(N,
typename A)>
600 struct NewCtorWithClassReference<SIGNATURE> : CtorBase<SIGNATURE> {
601 typedef CtorBase<SIGNATURE> Base;
602 typedef typename Base::Sig Sig;
603 NewCtorWithClassReference(Sig *func) { Base::SetFunc(func); }
606 static bp::object __new__(PARAMLIST) {
607 typedef typename CLS::metadata::held_type HeldType;
609 R r(Base::_func(ARGLIST));
611 if (TfPyConvertTfErrorsToPythonException(m))
612 bp::throw_error_already_set();
618 bp::detail::initialize_wrapper(ret.ptr(), get_pointer(h));
620 bp::setattr(ret,
"__class__", a0);
622 InstallPolicy<R>::PostInstall(ret, r, h.GetUniqueIdentifier());
635 #undef ARG_TYPE_STR_A 636 #undef EXTRACT_REQ_ARG_A 638 #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.
TF_API void TfPyThrowTypeError(const char *msg)
Raises a Python TypeError with the given error msg and throws a boost::python::error_already_set exce...
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.
Reference-counted smart pointer utility class.
TF_API void TfPyThrowRuntimeError(const char *msg)
Raises a Python RuntimeError with the given error msg and throws a boost::python::error_already_set e...