简体   繁体   中英

Dynamically sized array of objects in Cython

How can I perform the equivalent of the following C++ code in Cython ?

typedef vector<double> dvec;
dvec *arr = new dvec[n]; // n is an unsigned int (unknown at compile time)

// do something with arr; for example...
arr[0].push_back(10);
cout << arr[0][0] << endl;

I've tried to malloc the memory for the n vectors, but then I do not know how to do a placement new in Cython. Any help would be greatly appreciated.

It doesn't seem like you can do array new ( new something[n] ) in Cython. The simplest solution would be to create 1-line C++ function to do array new and array delete, and call those instead.

template <typename T>
T* array_new(int n) {
    return new T[n];
}

template <typename T>
void array_delete(T* x) {
    delete [] x;
}

Called from the following Cython file

# distutils: language = c++

from libcpp.vector cimport vector

ctypedef vector[double] dvec

cdef extern from "cpp_funcs.hpp":
    T* array_new[T](int)
    void array_delete[T](T* x)

def example(int n):
    cdef dvec* arr = array_new[dvec](n)
    try:
        if n>0:
            arr[0].push_back(10)
            print(arr[0][0])
    finally:
        array_delete(arr)

Given that Cython's C++ support is limited, and awkward in places (and given that you have to have a pretty good understanding of C++ to use it anyway) I think that writing a small amount of C++ code is usually a reasonable solution, and can save quite a bit of time. Some people seem to want to avoid this at all costs though....


I'd still recommend using a vector of vectors ( vector<vector<double>> ) instead since you get the memory management for free. Even better would be to stick with Python types and use a list of numpy arrays, but that might not be suitable if you want to interface with external C++ code.

As an addition to @DavidW's answer: Since Cython 0.28 there is a new feature which allows verbatim C-code . Its advantage is a seamless usage of such small C/C++-wrappers:

cdef extern from *:
    """
    template <typename T>
    T* array_new(int n) {
        return new T[n];
    }

    template <typename T>
    void array_delete(T* x) {
        delete [] x;
    }
    """
    T* array_new[T](int)
    void array_delete[T](T* x)

from libcpp.vector cimport vector
.... and so on

without the need for creating an extern header-file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM