TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
make_py_capsule.hpp
1// Copyright (c) 2018--present, The Simons Foundation
2// This file is part of TRIQS/nda and is licensed under the Apache License, Version 2.0.
3// SPDX-License-Identifier: Apache-2.0
4// See LICENSE in the root of this distribution for details.
5
6#pragma once
7
8// SHOULD ONLY BE INCLUDED in a python module.
9
10#include <Python.h>
11#include <numpy/arrayobject.h>
12#include <nda/nda.hpp>
13
14namespace nda::python {
15
16 // ------------- make_handle ------------
17
19 static inline void py_decref(void *x) { Py_DECREF((PyObject *)x); }
20
21 // Take a handle on a numpy. numpy is a borrowed Python ref.
22 // implemented only in Python module, not in triqs cpp
23 template <typename T>
24 nda::mem::handle_shared<T> make_handle(PyObject *obj) {
25
26 if (obj == NULL) throw std::runtime_error(" Can not build an mem_blk_handle from a NULL PyObject *");
27 if (!PyArray_Check(obj)) throw std::runtime_error("Internal error : ref_counter construct from pyo : obj is not an array");
28
29 // We create a new shared handle -> increase refcount
30 Py_INCREF(obj);
31
32 PyArrayObject *arr = (PyArrayObject *)(obj);
33
34 nda::mem::handle_shared<T> r{
35 (T *)PyArray_DATA(arr), // data
36 size_t(PyArray_SIZE(arr)), // size
37 obj, // foreign_handle
38 (void *)&py_decref // foreign_decref
39 };
40 return r;
41 }
42
43 // ------------------ delete_pycapsule ----------------------------------------------------
44
45 // Properly delete the nda::mem::handle_shared<T> in a PyCapsule
46 template <typename T>
47 static void delete_pycapsule(PyObject *capsule) {
48 nda::mem::handle_shared<T> *handle = static_cast<nda::mem::handle_shared<T> *>(PyCapsule_GetPointer(capsule, "guard"));
49 //std::cerr << "decapsulate : "<< handle->id << " "<< handle->data << " nrefs" << handle->nref() << "\n";
50 delete handle;
51 }
52
53 // ------------------ make_pycapsule, ----------------------------------------------------
54
55 // Make a pycapsule out of the shared handle to return to Python
56 template <typename T>
57 PyObject *make_pycapsule(nda::mem::handle_heap<T> const &h) {
58 void *keep = new nda::mem::handle_shared<T>{h}; // a new reference
59 return PyCapsule_New(keep, "guard", &delete_pycapsule<T>);
60 }
61
62 template <typename T>
63 PyObject *make_pycapsule(nda::mem::handle_borrowed<T> const &h) {
64 using U = std::remove_const_t<T>;
65 if (h.parent() == nullptr) throw std::runtime_error("Can not return to python a view on something else than an nda::array");
66 void *keep = new nda::mem::handle_shared<U>{*h.parent()}; // a new reference
67 return PyCapsule_New(keep, "guard", &delete_pycapsule<T>);
68 }
69
70} // namespace nda::python
Includes all relevant headers for the core nda library.
handle_heap< T0 > const * parent() const
Get a pointer to the parent handle.
Definition handle.hpp:921