// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef PXR_BASE_TF_PY_NOTICE_WRAPPER_H #define PXR_BASE_TF_PY_NOTICE_WRAPPER_H #include "pxr/pxr.h" #include "pxr/base/tf/notice.h" #include "pxr/base/tf/stringUtils.h" #include "pxr/base/tf/staticData.h" #include "pxr/base/tf/type.h" #include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/pyObjectFinder.h" #include "pxr/base/tf/wrapTypeHelpers.h" #include #include #include #include #include #include #include #include #include #include PXR_NAMESPACE_OPEN_SCOPE struct Tf_PyNoticeObjectGenerator { typedef Tf_PyNoticeObjectGenerator This; typedef boost::python::object (*MakeObjectFunc)(TfNotice const &); // Register the generator for notice type T. template static void Register() { // XXX this stuff should be keyed directly off TfType now (*_generators)[typeid(T).name()] = This::_Generate; } // Produce a boost::python::object for the correct derived type of \a n. TF_API static boost::python::object Invoke(TfNotice const &n); private: template static boost::python::object _Generate(TfNotice const &n) { // Python locking is left to the caller. return boost::python::object(static_cast(n)); } static MakeObjectFunc _Lookup(TfNotice const &n); TF_API static TfStaticData > _generators; }; struct TfPyNoticeWrapperBase : public TfType::PyPolymorphicBase { TF_API virtual ~TfPyNoticeWrapperBase(); virtual boost::python::handle<> GetNoticePythonObject() const = 0; }; template struct Tf_PyNoticeObjectFinder : public Tf_PyObjectFinderBase { virtual ~Tf_PyNoticeObjectFinder() {} virtual boost::python::object Find(void const *objPtr) const { using namespace boost::python; TfPyLock lock; Notice const *wrapper = static_cast(objPtr); return wrapper ? object(wrapper->GetNoticePythonObject()) : object(); } }; template struct TfPyNoticeWrapper : public NoticeType, public TfPyNoticeWrapperBase { private: static_assert(std::is_base_of::value || std::is_same::value, "Notice type must be derived from or equal to TfNotice."); static_assert(std::is_base_of::value || std::is_same::value, "BaseType type must be derived from or equal to TfNotice."); static_assert(std::is_base_of::value || (std::is_same::value && std::is_same::value), "BaseType type must be a base of notice, unless both " "BaseType and Notice type are equal to TfNotice."); public: typedef TfPyNoticeWrapper This; // If Notice is really TfNotice, then this is the root of the hierarchy and // bases is empty, otherwise bases contains the base class. typedef typename boost::mpl::if_< boost::is_same , boost::python::bases<>, boost::python::bases >::type Bases; typedef boost::python::class_ ClassType; static ClassType Wrap(std::string const &name = std::string()) { std::string wrappedName = name; if (wrappedName.empty()) { // Assume they want the last bit of a qualified name. wrappedName = TfType::Find().GetTypeName(); if (!TfStringGetSuffix(wrappedName, ':').empty()) wrappedName = TfStringGetSuffix(wrappedName, ':'); } Tf_PyNoticeObjectGenerator::Register(); Tf_RegisterPythonObjectFinderInternal (typeid(TfPyNoticeWrapper), new Tf_PyNoticeObjectFinder); return ClassType(wrappedName.c_str(), boost::python::no_init) .def(TfTypePythonClass()); } // Implement the base class's virtual method. virtual boost::python::handle<> GetNoticePythonObject() const { TfPyLock lock; return boost::python::handle<>(boost::python::borrowed(_self)); } // Arbitrary argument constructor (with a leading PyObject *) which // forwards to the base Notice class's constructor. template TfPyNoticeWrapper(PyObject *self, Args... args) : NoticeType(args...) , _self(self) {} private: PyObject *_self; }; #define TF_INSTANTIATE_NOTICE_WRAPPER(T, Base) \ TF_REGISTRY_FUNCTION(TfType) \ { \ TfType::Define< TfPyNoticeWrapper, \ TfType::Bases >(); \ } PXR_NAMESPACE_CLOSE_SCOPE #endif // PXR_BASE_TF_PY_NOTICE_WRAPPER_H