73#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSHADOW_OBJECT_H
74#define LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSHADOW_OBJECT_H
161enum ShadoweeConstness
170class LASS_PYTHON_DLL ShadowBaseCommon:
public PyObjectPlus
177 ~ShadowBaseCommon()
override;
179 void registerShadowee(
TShadoweeID shadoweeID, ShadoweeConstness constness);
180 void unregisterShadowee(
TShadoweeID shadoweeID, ShadoweeConstness constness);
182 typedef std::pair<TShadoweeID, ShadoweeConstness> TCacheKey;
186 std::size_t operator()(
const TCacheKey& key)
const
188 std::size_t h1 = std::hash<TShadoweeID>()(key.first);
189 std::size_t h2 = std::hash<ShadoweeConstness>()(key.second);
194 typedef std::unordered_map<TCacheKey, ShadowBaseCommon*, CacheKeyHash> TCache;
195 ShadowBaseCommon(
const ShadowBaseCommon&);
196 ShadowBaseCommon& operator=(
const ShadowBaseCommon&);
198 static TCache& cache();
205struct IsShadowClass:
public meta::IsDerived<T, ShadowBaseCommon>
215 enum { isShadow = IsShadowClass<T>::value };
219 template <
typename U,
bool shadow>
222 typedef typename U::TShadoweePtr TCppClassPtr;
223 typedef typename U::TConstShadoweePtr TConstCppClassPtr;
224 typedef typename U::TShadowPtr TPyClassPtr;
225 typedef typename U::TShadowee TCppClass;
226 static int getObject(U* obj, TCppClassPtr& value)
228 typedef typename U::TPointerTraits TPointerTraits;
229 const TCppClassPtr p = TPointerTraits::staticCast(obj->cppObject());
230 if (TPointerTraits::isEmpty(p))
232 PyErr_Format(PyExc_TypeError,
"PyObject is a const %s", T::_lassPyClassDef.name());
238 static int getObject(U* obj, TConstCppClassPtr& value)
240 typedef typename U::TConstPointerTraits TConstPointerTraits;
241 value = TConstPointerTraits::staticCast(obj->constCppObject());
242 if (TConstPointerTraits::isEmpty(value))
244 PyErr_Format(PyExc_TypeError,
"Trying to dereference null-PyObject of type %s", T::_lassPyClassDef.name());
249 template <
typename Ptr>
static TPyClassPtr buildObject(
const Ptr& value)
251 return U::make(value);
255 template <
typename U>
256 struct Impl<U, false>
258 typedef typename PyObjectPtr<U>::Type TPyClassPtr;
259 typedef TPyClassPtr TCppClassPtr;
260 typedef typename PyObjectPtr<const U>::Type TConstCppClassPtr;
262 static int getObject(U* obj, TPyClassPtr& value)
267 static int getObject(U* obj, TConstCppClassPtr& value)
272 static const TPyClassPtr& buildObject(
const TPyClassPtr& value)
279 typedef Impl<T, isShadow> TImpl;
281 static bool checkSubType(PyObject* obj)
284 if (!PyType_IsSubtype(obj->ob_type , T::_lassPyClassDef.type() ))
286 PyErr_Format(PyExc_TypeError,
"%s not castable to %s", obj->ob_type->tp_name, T::_lassPyClassDef.name());
294 typedef typename TImpl::TCppClass TCppClass;
295 typedef typename TImpl::TCppClassPtr TCppClassPtr;
296 typedef typename TImpl::TConstCppClassPtr TConstCppClassPtr;
297 typedef typename TImpl::TPyClassPtr TPyClassPtr;
298 typedef int (*TImplicitConverter)(PyObject* obj, TCppClassPtr&);
300 template <
typename Ptr>
static int getObject(PyObject* obj, Ptr& value)
307 if (PyType_IsSubtype(obj->ob_type , T::_lassPyClassDef.type()))
309 return TImpl::getObject(
static_cast<T*
>(obj), value);
312 if (tryImplicitConverters(obj, p) != 0)
319 static int getObject(PyObject* obj, TCppClass& value)
323 PyErr_Format(PyExc_TypeError,
"None not castable to %s", T::_lassPyClassDef.name());
327 if (obj->ob_type == T::_lassPyClassDef.type())
329 if (TImpl::getObject(
static_cast<T*
>(obj), p) != 0)
337 if (tryImplicitConverters(obj, p2) != 0)
347 LASS_PYTHON_CATCH_AND_RETURN_EX(1)
350 template <
typename Ptr>
static TPyClassPtr buildObject(
const Ptr& value)
352 return TImpl::buildObject(value);
354 static TPyClassPtr buildObject(
const TCppClass& value)
356 TCppClassPtr p(
new TCppClass(value));
357 return buildObject(p);
359 template <
typename Deleter>
360 static TPyClassPtr buildObject(std::unique_ptr<TCppClass, Deleter>&& value)
362 return buildObject(TCppClassPtr(std::move(value)));
364 static void addConverter(TImplicitConverter converter)
366 TImplicitConverterList* converters = implicitConverters();
367 converters->push_back(converter);
371 typedef std::vector<TImplicitConverter> TImplicitConverterList;
372 static TImplicitConverterList* implicitConverters_;
374 static int tryImplicitConverters(PyObject* obj, TCppClassPtr& p)
376 const TImplicitConverterList* converters = implicitConverters();
379 for (
typename TImplicitConverterList::const_iterator i = converters->begin(); i != converters->end(); ++i)
381 if ((*i)(obj, p) == 0)
388 PyErr_Format(PyExc_TypeError,
"%s not convertable to %s", obj->ob_type->tp_name, T::_lassPyClassDef.name());
392 static TImplicitConverterList* implicitConverters()
394 void*& slot = T::_lassPyClassDef.implicitConvertersSlot_;
397 slot =
new TImplicitConverterList;
399 return static_cast<TImplicitConverterList*
>(slot);
408template <
typename ShadowType,
typename DerivedMakers>
409typename ShadowType::TShadowPtr makeShadow(
410 const typename ShadowType::TConstShadoweePtr& shadowee,
const DerivedMakers* derivedMakers,
411 impl::ShadoweeConstness constness)
413 typedef typename ShadowType::TShadowPtr TShadowPtr;
414 typedef typename ShadowType::TConstPointerTraits TConstPointerTraits;
416 LASS_ASSERT(!TConstPointerTraits::isEmpty(shadowee));
417 if (
const auto p = impl::ShadowBaseCommon::findShadowObject(TConstPointerTraits::id(shadowee), constness))
419 LASS_ASSERT(PyObject_IsInstance(p.get(),
reinterpret_cast<PyObject*
>(ShadowType::_lassPyClassDef.type())));
420 return p.template staticCast<ShadowType>();
424 for (
typename DerivedMakers::const_iterator i = derivedMakers->begin(); i != derivedMakers->end(); ++i)
426 if (
const TShadowPtr p = (*i)(shadowee, constness))
432 return TShadowPtr(impl::fixObjectType(
new ShadowType(shadowee, constness)));
438template <
typename Makers,
typename Maker>
void registerMaker(Makers*& makers, Maker maker)
444 makers->push_back(maker);
450template <
typename DestPyType,
typename SourceCppType>
451int defaultConvertor(PyObject*
object,
typename lass::python::impl::ShadowTraits<DestPyType>::TCppClassPtr& p)
453 typedef typename lass::python::impl::ShadowTraits<DestPyType>::TCppClass TCppClass;
454 typedef typename lass::python::impl::ShadowTraits<DestPyType>::TCppClassPtr TPtr;
455 SourceCppType source;
456 if (pyGetSimpleObject(
object, source) != 0)
460 p = TPtr(
new TCppClass(source));
496 typedef util::SharedPtr<T, S, C>
TPtr;
537 template <
typename U>
static TPtr constCast(
const util::SharedPtr<U, S, C>& p)
587 return static_cast<TPtr>(p);
592 return dynamic_cast<TPtr>(p);
597 return const_cast<TPtr>(p);
609 typedef std::shared_ptr<T>
TPtr;
642 return std::static_pointer_cast<T>(p);
647 return std::dynamic_pointer_cast<T>(p);
652 return std::const_pointer_cast<T>(p);
664 typename ShadoweeType,
665 typename ParentShadowType,
666 typename PointerTraits = SharedPointerTraits<ShadoweeType>
668class ShadowClass:
public ParentShadowType
671 typedef ShadoweeType TShadowee;
672 typedef ShadowType TShadow;
673 typedef ParentShadowType TParentShadow;
674 typedef typename PointerTraits::template Rebind<ShadoweeType>::Type TPointerTraits;
675 typedef typename PointerTraits::template Rebind<const ShadoweeType>::Type TConstPointerTraits;
676 typedef typename TPointerTraits::TPtr TShadoweePtr;
677 typedef typename TConstPointerTraits::TPtr TConstShadoweePtr;
678 typedef typename PyObjectPtr<ShadowType>::Type TShadowPtr;
680 static TShadowPtr make(
const TShadoweePtr& shadowee)
682 return impl::makeShadow<ShadowType>(shadowee, derivedMakers_, impl::scNonConst);
684 static TShadowPtr make(
const TConstShadoweePtr& shadowee)
686 return impl::makeShadow<ShadowType>(shadowee, derivedMakers_, impl::scConst);
688 static void registerWithParent()
690 ParentShadowType::registerDerivedMaker(ShadowClass::makeParent);
694 typedef TShadowPtr (*TDerivedMaker)(
const TConstShadoweePtr&, impl::ShadoweeConstness);
696 ShadowClass(
const TConstShadoweePtr& shadowee, impl::ShadoweeConstness constness):
697 ParentShadowType(shadowee, constness)
700 static void registerDerivedMaker(TDerivedMaker derivedMaker)
702 impl::registerMaker(derivedMakers_, derivedMaker);
706 typedef std::vector<TDerivedMaker> TDerivedMakers;
708 typedef typename TParentShadow::TConstShadoweePtr TParentConstShadoweePtr;
709 typedef typename TParentShadow::TShadowPtr TParentShadowPtr;
711 static TParentShadowPtr makeParent(
const TParentConstShadoweePtr& shadowee, impl::ShadoweeConstness constness)
713 const TConstShadoweePtr p = TConstPointerTraits::dynamicCast(shadowee);
714 if (TConstPointerTraits::isEmpty(p))
716 return TParentShadowPtr();
718 return impl::makeShadow<ShadowType>(p, derivedMakers_, constness);
721 static TDerivedMakers* derivedMakers_;
724template <
typename S,
typename T,
typename P,
typename PT>
725typename ShadowClass<S, T, P, PT>::TDerivedMakers* ShadowClass<S, T, P, PT>::derivedMakers_ = 0;
735 typename ShadoweeType,
736 typename PointerTraits
738class ShadowClass<ShadowType, ShadoweeType,
PyObjectPlus, PointerTraits>:
public impl::ShadowBaseCommon
741 typedef ShadoweeType TShadowee;
742 typedef ShadowType TShadow;
743 typedef typename PointerTraits::template Rebind<ShadoweeType>::Type TPointerTraits;
744 typedef typename PointerTraits::template Rebind<const ShadoweeType>::Type TConstPointerTraits;
745 typedef typename TPointerTraits::TPtr TShadoweePtr;
746 typedef typename TConstPointerTraits::TPtr TConstShadoweePtr;
747 typedef typename PyObjectPtr<ShadowType>::Type TShadowPtr;
749 const TShadoweePtr cppObject()
const
751 if (constness_ == impl::scConst)
753 return TShadoweePtr();
755 return TPointerTraits::constCast(shadowee_);
757 const TConstShadoweePtr& constCppObject()
const
761 static TShadowPtr make(
const TShadoweePtr& shadowee)
763 return impl::makeShadow<ShadowType>(shadowee, derivedMakers_, impl::scNonConst);
765 static TShadowPtr make(
const TConstShadoweePtr& shadowee)
767 return impl::makeShadow<ShadowType>(shadowee, derivedMakers_, impl::scConst);
769 static void registerWithParent()
773 typedef TShadowPtr (*TDerivedMaker)(
const TConstShadoweePtr&, impl::ShadoweeConstness);
774 ShadowClass(
const TConstShadoweePtr& shadowee, impl::ShadoweeConstness constness):
776 constness_(constness)
778 TConstPointerTraits::acquire(shadowee_);
779 impl::ShadowBaseCommon::registerShadowee(TConstPointerTraits::id(shadowee_), constness_);
783 impl::ShadowBaseCommon::unregisterShadowee(TConstPointerTraits::id(shadowee_), constness_);
784 TConstPointerTraits::release(shadowee_);
786 static void registerDerivedMaker(TDerivedMaker derivedMaker)
788 impl::registerMaker(derivedMakers_, derivedMaker);
791 typedef std::vector<TDerivedMaker> TDerivedMakers;
793 static TDerivedMakers* derivedMakers_;
794 TConstShadoweePtr shadowee_;
795 impl::ShadoweeConstness constness_;
798template <
typename S,
typename T,
typename PT>
799typename ShadowClass<S, T, PyObjectPlus, PT>::TDerivedMakers* ShadowClass<S, T, PyObjectPlus, PT>::derivedMakers_ = 0;
825template <
typename ShadoweeType>
826using ShadoweePtr = std::conditional_t<std::is_const_v<ShadoweeType>,
827 typename impl::ShadowTraits<typename ShadoweeTraits<ShadoweeType>::TShadow>::TConstCppClassPtr,
828 typename impl::ShadowTraits<typename ShadoweeTraits<ShadoweeType>::TShadow>::TCppClassPtr
845#define PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectParent, t_PointerTraits) \
846 class dllInterface i_PyObjectShadowClass : \
847 public ::lass::python::ShadowClass< i_PyObjectShadowClass, t_CppClass, t_PyObjectParent, t_PointerTraits > \
849 PY_HEADER(t_PyObjectParent) \
850 static void _lassPyClassRegisterHook() { registerWithParent(); } \
852 i_PyObjectShadowClass(const TConstShadoweePtr& shadowee, ::lass::python::impl::ShadoweeConstness constness): \
853 ::lass::python::ShadowClass< i_PyObjectShadowClass, t_CppClass, t_PyObjectParent, t_PointerTraits >(shadowee, constness) \
870#define PY_SHADOW_CLASS_PTRTRAITS(dllInterface, i_PyObjectShadowClass, t_CppClass, pointerTraits)\
871 PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, ::lass::python::PyObjectPlus, pointerTraits < t_CppClass > )
880#define PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)\
881 PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, ::lass::python::PyObjectPlus, ::lass::python::SharedPointerTraits< t_CppClass >)
898#define PY_SHADOW_CLASS_DERIVED(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)\
899 PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent, t_PyObjectShadowParent::TPointerTraits::Rebind< t_CppClass >::Type )
905#define PY_SHADOW_CLASS_NOCONSTRUCTOR_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectBase, t_PyObjectParent)\
906 PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectBase, t_PyObjectParent)
912#define PY_SHADOW_CLASS_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass)\
913 PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
919#define PY_WEAK_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)\
920 PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
926#define PY_WEAK_SHADOW_CLASS_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass)\
927 PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
933#define PY_SHADOW_CLASS_ENABLE_AUTOMATIC_INVALIDATION(i_PyObjectShadowClass)
939#define PY_SHADOW_CLASS_DERIVED_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)\
940 PY_SHADOW_CLASS_DERIVED(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)
961#define PY_SHADOW_CASTERS(t_ShadowObject)\
966 template <> struct ShadoweeTraits< t_ShadowObject::TShadowee >: ::lass::meta::True \
968 typedef t_ShadowObject TShadow; \
970 typedef t_ShadowObject::TPointerTraits TPointerTraits; \
982#define PY_SHADOW_DOWN_CASTERS(t_ShadowObject)\
983 PY_SHADOW_CASTERS(t_ShadowObject)
989#define PY_SHADOW_DOWN_CASTERS_NOCONSTRUCTOR(t_ShadowObject)\
990 PY_SHADOW_CASTERS(t_ShadowObject)
1055#define PY_CLASS_CONVERTOR_EX( t_ShadowObject, f_conversionFunction, i_uniqueName )\
1056 LASS_EXECUTE_BEFORE_MAIN_EX( LASS_CONCATENATE( lassPyClassConverter_, i_uniqueName ),\
1057 lass::python::impl::ShadowTraits< t_ShadowObject >::addConverter( f_conversionFunction );\
1107#define PY_CLASS_CONVERTOR( i_ShadowObject, t_sourceType )\
1108 PY_CLASS_CONVERTOR_EX( i_ShadowObject, (::lass::python::impl::defaultConvertor< i_ShadowObject, t_sourceType >) , i_ShadowObject );
The default counter for the shared pointers, implementation of CounterPolicy concept.
Default storage policy for single objects, implementation of StoragePolicy concept.
PyObjectPtr< PyObject >::Type TPyObjPtr
PyObjectPtr to a PyObject.
lass::util::SharedPtr< T, PyObjectStorage, PyObjectCounter > fromNakedToSharedPtrCast(PyObject *object)
fromNakedToSharedPtrCast.
num::TuintPtr TShadoweeID
ID-type to uniquely identify shadowee instances in the shadow cache.
std::conditional_t< std::is_const_v< ShadoweeType >, typename impl::ShadowTraits< typename ShadoweeTraits< ShadoweeType >::TShadow >::TConstCppClassPtr, typename impl::ShadowTraits< typename ShadoweeTraits< ShadoweeType >::TShadow >::TCppClassPtr > ShadoweePtr
Helper to get the pointer type holding the shadowee in a shadow object.
Comprehensive C++ to Python binding library.
Library for Assembled Shared Sources.
Rebind pointer traits to other shadowee type.
Pointer-traits for Python Shadow classes that use raw * pointers for storage.
static void release(TPtr)
Raw pointers have no ownership rules.
static TPtr staticCast(U *p)
Perform static cast on shadowee pointer.
static void acquire(TPtr)
Raw pointers have no ownership rules.
static TPtr dynamicCast(U *p)
Perform dynamic cast on shadowee pointer.
static TPtr constCast(U *p)
Perform const cast on shadowee pointer.
static T * get(TPtr p)
Get the raw pointer to the shadowee.
T * TPtr
Pointer to shadowee type.
static TShadoweeID id(TPtr p)
Convert shadowee pointer to ID for shadow cache.
static bool isEmpty(TPtr p)
Return true when storing a nullptr.
Rebind pointer traits to other shadowee type.
Pointer-traits for Python Shadow classes that use lass::util::SharedPtr for storage.
static bool isEmpty(const TPtr &p)
Return true when storing a nullptr.
static void acquire(const TPtr &)
util::SharedPtr already handles reference counts
static TPtr dynamicCast(const util::SharedPtr< U, S, C > &p)
Perform dynamic cast on shadowee pointer.
util::SharedPtr< ContainerType, util::ObjectStorage, util::DefaultCounter > TPtr
static void release(const TPtr &)
util::SharedPtr already handles reference counts
static T * get(const TPtr &p)
Get the raw pointer to the shadowee.
static TPtr staticCast(const util::SharedPtr< U, S, C > &p)
Perform static cast on shadowee pointer.
static TShadoweeID id(const TPtr &p)
Convert shadowee pointer to ID for shadow cache.
static TPtr constCast(const util::SharedPtr< U, S, C > &p)
Perform const cast on shadowee pointer.
Rebind pointer traits to other shadowee type.
Pointer-traits for Python Shadow classes that use std::shared_ptr for storage.
static void acquire(const TPtr &)
std::shared_ptr already handles reference counts
static void release(const TPtr &)
std::shared_ptr already handles reference counts
static TPtr constCast(const std::shared_ptr< U > &p)
Perform const cast on shadowee pointer.
static TShadoweeID id(TPtr p)
Convert shadowee pointer to ID for shadow cache.
static bool isEmpty(const TPtr &p)
Return true when storing a nullptr.
static TPtr staticCast(const std::shared_ptr< U > &p)
Perform static cast on shadowee pointer.
static TPtr dynamicCast(const std::shared_ptr< U > &p)
Perform dynamic cast on shadowee pointer.
static T * get(const TPtr &p)
Get the raw pointer to the shadowee.
std::shared_ptr< T > TPtr
Pointer to shadowee type.