python - 在 Cython 中包装返回复杂类型 Vector 的函数

标签 python c++ vector cython complex-numbers

我目前正在尝试包装我创建的 C++ 类。其中一个函数返回包含复杂 float 的 vector vector :

std::vector<std::vector<std::complex<float>>>

我的DataBridge.pxd文件如下所示:

# distutils: language = c++

from libcpp cimport bool
from libcpp cimport float
from libcpp.vector cimport vector
from libcpp.complex cimport complex

from libc.float cimport float

cimport numpy as np
import numpy as np

cdef extern from "projectxcpp/bridge.cpp":
    pass

# Declare the class with cdef
cdef extern from "projectxcpp/bridge.hpp":
    cdef cppclass DataBridge:
        DataBridge() except +
        void start()
        void stop()
        bool isDataReady()
        vector[vector[complex[float]]] getData()

我的bridge.hpp文件如下所示:

#ifndef BRIDGE_HPP
#define BRIDGE_HPP

#include <vector>
#include <complex>

...

class DataBridge {
    public:
        int start(void);
        int stop(void);

        bool isDataReady(void);
        std::vector<std::vector<std::complex<float>>> getData(void);

    private:
        ...
};

#endif

然后,尝试运行 setup.py,给出以下消息:

[1/1] Cythonizing snowconecpp.pyx

Error compiling Cython file:
------------------------------------------------------------
...
        DataBridge() except +
        void start()
        void stop()
        bool isDataReady()
        vector[vector[complex[float]]] getData()
                            ^
------------------------------------------------------------

DataBridge.pxd:24:29: Array size must be a compile time constant

Error compiling Cython file:
------------------------------------------------------------
...
        DataBridge() except +
        void start()
        void stop()
        bool isDataReady()
        vector[vector[complex[float]]] getData()
                            ^
------------------------------------------------------------

DataBridge.pxd:24:29: unknown type in template argument
Traceback (most recent call last):
  File "setup.py", line 15, in <module>
    setup(ext_modules=cythonize("projectxcpp.pyx", language_level="3"))
  File ".../lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1096, in cythonize
    cythonize_one(*args)
  File ".../lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1219, in cythonize_one
    raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: projectxcpp.pyx

我的 setup.py 文件只包含:

from distutils.core import setup

from Cython.Build import cythonize

setup(ext_modules=cythonize("projectxcpp.pyx", language_level="3"))

在我的包装器中将类型声明为 complex[float] evector[vector[float]] e ,这些将解析并移动到下一步的编译。

只是想知道是否有将复杂类型放入 Cython 的 vector 中的特殊要求 - 似乎无法为涉及 C++ 包装的这种或类似情况找到答案。

我的最终目标是能够将这些数据读出到一个 numpy 数组中。如果有更好的方法来解决这个问题,也请告诉我 - 谢谢!

最佳答案

我认为问题在于 complex 已经是 Python/Cython 中的一种类型(由于与 C 或 C++ complex 的重叠,它在某些地方也处理得有点糟糕......)。如果您重命名它,或者通过它的完整路径解决它,它就会起作用

from libcpp.complex cimport complex as cpp_complex

# later
vector[vector[cpp_complex[float]]]

cimport libcpp.complex

# later
vector[vector[libcpp.complex.complex[float]]]

对于问题的更一般性部分:我的偏好是不要像那样为 Numpy 数组提供数据。部分原因是我真的不喜欢将 2D 数组定义为指针到指针或 vector 的 vector 。您最好使用与形状信息一起存储的一维数组/vector ,以便对其进行索引。

有几个与 Numpy 交互的选项:

  1. 如果您事先知道大小,则使用 Numpy 分配内存并将该内存传递给 C++(您可以获得指向 Numpy 数组第一个元素的指针)。这样,C++ 代码就可以修改 Numpy 的内存,而您不必复制数据。

  2. 如果你想用 C++ 分配内存,那么你可以用一个 Cython 类包装它 implements the buffer protocol .内存由C++管理,但Numpy可以直接访问内存而无需复制。 (您可能需要实现移动构造函数以避免复制,但这相当简单)。

  3. 您可以使用 Numpy C API 函数 PyArray_SimpleNewFromData 让 Numpy 包装内存。这需要小心确保它在正确的时间被释放。

  4. 您可以做您当前正在做的事情,然后将数据复制过来。这实现起来非常简单,但每次您想将数据从 C++ 移动到 Python 时都会添加一个复制操作。

关于python - 在 Cython 中包装返回复杂类型 Vector 的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57956131/

相关文章:

python - 如何获取两个单词之间列表的子列表

python - 即使对于服务器上的单个基于 django 的应用程序,是否也建议使用 virtualenv?

c++ - 将模板函数传递给模板函数

c++ - vector 迭代器 -> 打印类(缺少参数)

r - 根据条件将命名数值向量(按升序)转换为命名逻辑向量

python - pandas 多索引 DataFrame 中的圆形 float

python - 对 Python 中 Pandas 的多列 groupby 操作的含义感到困惑

c++ - 如何在 C++ 中取一个字节的二进制补码?

c++ - 通用 lambda 的熟悉模板语法

java - 在 Java vector 中插入 null