//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      PyCore/Embed/PyObjectPtr.h
//! @brief     Defines class PyObjectPtr and struct NumpyArrayDescriptor.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#ifdef SWIG
#error no need to expose this header to Swig
#endif // SWIG
#ifndef BORNAGAIN_PYTHON
#error this header requires Python support
#endif
#ifndef BORNAGAIN_PYCORE_EMBED_PYOBJECTPTR_H
#define BORNAGAIN_PYCORE_EMBED_PYOBJECTPTR_H

#include "PyCore/Embed/PyObjectDecl.h"

//! Safe container for PyObjects:
//! The class `PyObjectPtr` contains a `PyObject*` (or `NULL`).
//! Decrementing Python reference-count is performed automatically when
//! the life-time of a `PyObjectPtr` expires.
class PyObjectPtr {
public:
    PyObjectPtr(PyObject* pyobject_ptr);
    ~PyObjectPtr();
    PyObjectPtr(const PyObjectPtr&) = delete;
    PyObjectPtr(PyObjectPtr&& other);
    PyObjectPtr& operator=(const PyObjectPtr&) = delete;

    //! Returns the raw pointer to the PyObject
    PyObject* get() { return m_ptr; }
    //! Resets the container to the initial status (does _not_ release the Python resource)
    void reset();
    //! Resets the container to the initial status and return the PyObject pointer
    //! (does _not_ release the Python resource)
    PyObject* release();
    //! Discards the Python resource (decrements the Python reference)
    void discard();
    //! Check the validity of the PyObjectPtr
    bool valid() const;

private:
    //! Raw pointer to the PyObject
    PyObject* m_ptr = nullptr;
};

#endif // BORNAGAIN_PYCORE_EMBED_PYOBJECTPTR_H
