gpt4 book ai didi

python - 在 Cython 中定义 C++ 结构返回类型

转载 作者:太空狗 更新时间:2023-10-29 21:13:35 24 4
gpt4 key购买 nike

我编写了一个小型 C++ 库来模拟 ODE 系统,并使用 Cython 包装了一个初始化和求解系统的函数。 C++ 函数接受少量参数,并返回一个包含两个矩阵的结构:一组用于构建系统的模式,以及系统的已解决状态每个时间步。

这些矩阵是使用 Eigen 实现的库,所以我正在使用 Eigency将这些数据结构的底层内容传输到 NumPy 数组的接口(interface)。

如果在 Python 中,我返回这些矩阵之一的 View ,一切都很好。但是,我想返回一个包含这两个矩阵的元组,这需要临时存储这个结构,然后返回它的每个矩阵成员:

## kernel.pyx

from eigency.core cimport *

cdef extern from "kernel_cpp.h":

cdef cppclass network:
MatrixXf state
MatrixXf patterns

cdef network _run "run" (int N, int K, int P, double g, double T, double tau, double dt)

def run(N=10000, K=100, P=30, g=1.5, T=0.5, tau=1e-3, dt=1e-3):
return ndarray_view(_run(N,K,P,g,T,tau,dt).state) # <--- This works
# This does not:
# cdef network net = _run(N,K,P,g,T,tau,dt):
# return (ndarray_view(net.state), ndarray_view(net.patterns))

我在使用 python setup.py build_ext --inplace 构建注释代码时遇到的错误是

kernel.cpp:1552:11: error: no matching constructor for initialization of 'network'
network __pyx_v_net;
^`

这对我来说很有意义——Cython 正在尝试调用网络的构造函数。但我希望构建在“运行”中进行。此处正确的类型声明是什么?

如果有帮助,代码的精简版本是 here .

谢谢!

最佳答案

值得了解 Cython 如何翻译堆栈分配 C++ 变量的代码:

def run(N=10000, K=100, P=30, g=1.5, T=0.5, tau=1e-3, dt=1e-3):
cdef network net = _run(N,K,P,g,T,tau,dt)

函数内部被翻译成:

{
// start of function
network net; // actually some mangled variable name (see your error message)

// body of function
net = _run(N,K,P,g,T,tau,dt);
}

即它需要默认构造函数和复制/移动赋值运算符。这与 C++ 代码的编写方式不符,因此偶尔会导致问题。 Cython 通常假定这些存在(除非您告诉它其他构造函数),因此您不需要在 cdef cppclass block 中显式写出这些。

我认为您的错误消息看起来是在编译 C++ 代码时出现的,它没有定义默认构造函数。 (稍后的复制赋值应该不是问题,因为 C++ 会自动生成它)。您有两个选择:

  1. 如果您喜欢修改 C++ 代码,那么请定义一个默认构造函数。这将允许 Cython 代码按照编写的方式工作。如果您使用的是 >=C++11 那么这可能很简单:

    network() = default;

    这可能不起作用,具体取决于内部 Eigen 类型是否可以默认构造。

  2. 如果您不想修改 C++ 代码,或者发现您无法轻松定义默认构造函数,那么您将不得不修改 Cython 代码以分配网络new。这也意味着您必须自己处理重新分配:

      # earlier
    cdef cppclass network:
    # need to tell Cython about copy constructor
    network(const network&)
    # everything else as before

    def run(N=10000, K=100, P=30, g=1.5, T=0.5, tau=1e-3, dt=1e-3):
    cdef network* net
    try:
    net = new network(_run(N,K,P,g,T,tau,dt))
    return (ndarray_view(net.state), ndarray_view(net.patterns))
    finally:
    del net

    在这种情况下,不需要默认构造函数,只需要一个复制/移动构造函数(无论如何你必须拥有它才能从函数返回一个网络)。注意使用 finally 来确保释放内存。

关于python - 在 Cython 中定义 C++ 结构返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43688592/

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