gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-28 04:10:17 26 4
gpt4 key购买 nike

我目前正在尝试包装我创建的 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com