From 032cea587dc6a4aabed4fcaec1af7c2877363707 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 4 Mar 2022 15:51:51 +0100 Subject: [PATCH] Base: implement a lightweight smart pointer for PyObject like Py::Object to reduce includes of Python.h in header files --- src/App/DocumentObject.h | 3 +- src/App/ObjectIdentifier.cpp | 1 + src/App/ObjectIdentifier.h | 5 +- src/App/Property.cpp | 1 + src/App/PropertyFile.cpp | 1 + src/Base/CMakeLists.txt | 2 + src/Base/SmartPtrPy.cpp | 119 ++++++++++++++++++++++++ src/Base/SmartPtrPy.h | 86 +++++++++++++++++ src/Mod/Measure/App/Measurement.h | 3 +- src/Mod/Spreadsheet/App/PropertySheet.h | 3 +- 10 files changed, 219 insertions(+), 5 deletions(-) create mode 100644 src/Base/SmartPtrPy.cpp create mode 100644 src/Base/SmartPtrPy.h diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index eec28a5396..30ffe02880 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -609,7 +610,7 @@ protected: /// python object of this class and all descendent protected: // attributes - Py::Object PythonObject; + Py::SmartPtr PythonObject; /// pointer to the document this object belongs to App::Document* _pDoc; diff --git a/src/App/ObjectIdentifier.cpp b/src/App/ObjectIdentifier.cpp index 4fe209cad9..78776739e8 100644 --- a/src/App/ObjectIdentifier.cpp +++ b/src/App/ObjectIdentifier.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include "ObjectIdentifier.h" #include "Application.h" diff --git a/src/App/ObjectIdentifier.h b/src/App/ObjectIdentifier.h index a74868d43b..5bec35df13 100644 --- a/src/App/ObjectIdentifier.h +++ b/src/App/ObjectIdentifier.h @@ -30,10 +30,11 @@ #include #include #include -#include #include - +namespace Py { +class Object; +} namespace App { diff --git a/src/App/Property.cpp b/src/App/Property.cpp index 7dc5caa5d0..216f8506d8 100644 --- a/src/App/Property.cpp +++ b/src/App/Property.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "Property.h" #include "ObjectIdentifier.h" diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index 563ca2a8a6..8dc8cfe3e7 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #include +#include #include #include #include diff --git a/src/Base/CMakeLists.txt b/src/Base/CMakeLists.txt index c954558fcd..bbe8c09b9f 100644 --- a/src/Base/CMakeLists.txt +++ b/src/Base/CMakeLists.txt @@ -254,6 +254,7 @@ SET(FreeCADBase_CPP_SRCS Rotation.cpp RotationPyImp.cpp Sequencer.cpp + SmartPtrPy.cpp Stream.cpp Swap.cpp ${SWIG_SRCS} @@ -312,6 +313,7 @@ SET(FreeCADBase_HPP_SRCS Reader.h Rotation.h Sequencer.h + SmartPtrPy.h Stream.h Swap.h ${SWIG_HEADERS} diff --git a/src/Base/SmartPtrPy.cpp b/src/Base/SmartPtrPy.cpp new file mode 100644 index 0000000000..edd1c98ee4 --- /dev/null +++ b/src/Base/SmartPtrPy.cpp @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (c) 2020 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include "SmartPtrPy.h" +#include + + +namespace Py { + void SmartPtr::set(PyObject *pyob, bool owned) + { + release(); + p = pyob; + if( !owned ) + { + Py::_XINCREF( p ); + } + } + + void SmartPtr::release() + { + Py::_XDECREF( p ); + p = nullptr; + } + + SmartPtr::SmartPtr() + : p( Py::_None() ) + { + Py::_XINCREF( p ); + } + + SmartPtr::SmartPtr( PyObject *pyob, bool owned) + : p( pyob ) + { + if( !owned ) + { + Py::_XINCREF( p ); + } + } + + SmartPtr::SmartPtr( const SmartPtr &ob ) + : p( ob.p ) + { + Py::_XINCREF( p ); + } + + SmartPtr &SmartPtr::operator=( const Object &rhs ) + { + set( rhs.ptr() ); + return *this; + } + + SmartPtr &SmartPtr::operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + + return *this; + } + + SmartPtr::~SmartPtr() + { + release(); + } + + PyObject *SmartPtr::operator*() const + { + return p; + } + + PyObject *SmartPtr::ptr() const + { + return p; + } + + bool SmartPtr::is( PyObject *pother ) const + { // identity test + return p == pother; + } + + bool SmartPtr::is( const SmartPtr &other ) const + { // identity test + return p == other.p; + } + + bool SmartPtr::isNull() const + { + return p == nullptr; + } + + BaseExport PyObject* new_reference_to(const SmartPtr& g) { + PyObject* p = g.ptr(); + Py::_XINCREF(p); + return p; + } +} diff --git a/src/Base/SmartPtrPy.h b/src/Base/SmartPtrPy.h new file mode 100644 index 0000000000..28fa59cf99 --- /dev/null +++ b/src/Base/SmartPtrPy.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (c) 2020 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef PY_SMARTPTRPY_H +#define PY_SMARTPTRPY_H + +// forward declarations +typedef struct _object PyObject; + +namespace Py { +class Object; + +/** + * \brief This is a stripped-down version of Py::Object. + * The purpose of this class is to avoid to include any other header file + * and therefore the PyObject is forward declared and the implementation + * is separated from the class declaration. + * + * \author Werner Mayer + */ +class BaseExport SmartPtr +{ +private: + PyObject *p; + +protected: + void set(PyObject *pyob, bool owned = false); + void release(); + +public: + SmartPtr(); + + // Constructor acquires new ownership of pointer unless explicitly told not to. + explicit SmartPtr(PyObject *pyob, bool owned = false); + + // Copy constructor acquires new ownership of pointer + SmartPtr(const SmartPtr &ob); + + // Assignment acquires new ownership of pointer + SmartPtr &operator=( const Object &SmartPtr ); + + SmartPtr &operator=(PyObject *rhsp); + + // Destructor + virtual ~SmartPtr(); + + // Loaning the pointer to others, retain ownership + PyObject *operator*() const; + + // Would like to call this pointer() but messes up STL in SeqBase + PyObject *ptr() const; + // + // Queries + // + + bool is(PyObject *pother) const; + bool is(const SmartPtr &other) const; + + bool isNull() const; +}; + +BaseExport PyObject* new_reference_to(const SmartPtr&); + +} + +#endif // PY_SMARTPTRPY_H diff --git a/src/Mod/Measure/App/Measurement.h b/src/Mod/Measure/App/Measurement.h index bfbd1575f5..f94610a812 100644 --- a/src/Mod/Measure/App/Measurement.h +++ b/src/Mod/Measure/App/Measurement.h @@ -24,6 +24,7 @@ #define MEASURE_MEASUREMENT_H #include +#include #include #include @@ -84,7 +85,7 @@ public: protected: TopoDS_Shape getShape(App::DocumentObject *obj , const char *subName) const; MeasureType measureType; - Py::Object PythonObject; + Py::SmartPtr PythonObject; }; diff --git a/src/Mod/Spreadsheet/App/PropertySheet.h b/src/Mod/Spreadsheet/App/PropertySheet.h index 548f490eb8..b9081e7c29 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.h +++ b/src/Mod/Spreadsheet/App/PropertySheet.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "Cell.h" namespace Spreadsheet @@ -283,7 +284,7 @@ private: std::map revAliasProp; /*! The associated python object */ - Py::Object PythonObject; + Py::SmartPtr PythonObject; std::map depConnections;