繁体   English   中英

在 Cython 中包装返回复杂类型向量的函数

[英]Wrapping a function returning a Vector of Complex types in Cython

我目前正在尝试包装我创建的 C++ 类。 其中一个函数返回一个包含复数浮点数的向量:

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 的向量中 - 似乎无法找到这种或涉及 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 数组定义为指针到指针或向量向量。 您最好使用与形状信息一起存储的一维数组/向量,以便您对其进行索引。

有几种与 Numpy 接口的选项:

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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