重载 operator() 在 Cython 中失败

Posted

技术标签:

【中文标题】重载 operator() 在 Cython 中失败【英文标题】:Overloaded operator() is failing in Cython 【发布时间】:2020-05-22 18:30:39 【问题描述】:

我正在尝试使用 Cython 在 Python 中包装一个手写的模板化 C++ 数组类。代码无法编译,因为应该返回引用的operator() 在编译期间会触发错误:Cannot assign to or delete this。如何让我的代码编译?

我的.pyx 文件是:

# distutils: language = c++
import cython
import numpy as np
cimport numpy as np

cdef extern from "<array>" namespace "std":
    cdef cppclass Dim_array_2 "std::array<int, 2>":
        Dim_array_2() except+
        int& operator[](size_t)

cdef extern from "Array.h":
    cdef cppclass Array_2 "Array<double>":
        Array_2() except +
        void set_dims(const Dim_array_2&) except +
        double& operator()(const Dim_array_2&)

def print_index():
    cdef Dim_array_2 dims
    dims[0] = 3
    dims[1] = 5
    cdef Array_2 a
    a.set_dims(dims)

    cdef Dim_array_2 index

    counter = 0.
    for j in range(dims[1]):
        for i in range(dims[0]):
            index[0] = i+1
            index[1] = j+1
            a(index) = counter # This fails.
            counter += 1.

    index[0] = 2
    index[1] = 3
    print(a(index))

对应的C++Array.h的简化版是:

#include <array>
#include <vector>

template<typename TF>
class Array

    public:
        Array() 
        void set_dims(const std::array<int,2>& dims)
        
            data.resize(dims[0]*dims[1]);
            this->dims = dims;
        

        TF& data operator()(const std::array<int, 2>& index)
        
            return data[ (index[0]-1) + (index[1]-1)*dims[0] ];
        

    private:
        std::vector<TF> data;
        std::array<int,2> dims;
;

完整的错误信息是:

Error compiling Cython file:
------------------------------------------------------------
...
    counter = 0.
    for j in range(dims[1]):
        for i in range(dims[0]):
            index[0] = i+1
            index[1] = j+1
            a(index) = counter # This fails.
            ^
------------------------------------------------------------

test.pyx:31:13: Cannot assign to or delete this

【问题讨论】:

不应该是TF &amp; operator()吗?请发布完整的错误消息。 我正在尝试选择一种类型的模板化 Array 类。我已添加完整的错误消息。 【参考方案1】:

我认为operator[] 是专门用于工作的,所以它在所谓的类似情况下工作的事实并不能告诉你太多。

我认为总的来说 Cython 很难使这种语法工作。它不完全理解 C++ 引用,而且 C++ 调用经常使用临时变量(以帮助包装 C++ 异常处理),而这些绝对不能很好地与引用一起使用。

您可能不得不放弃“不错的”array(index) = value 语法,并编写一个小的 C++ 包装函数来帮助您:

cdef extern from "Array.h":
    """
    void setArrayValue(Array<double>& arr, const std::array<int, 2>& idx, double value) 
        arr(idx) = value;
    
    """
    # ...

(我使用 Cython 的文档字符串语法来包含小型 C/C++ 代码 sn-ps。)

在您的 Cython 代码中,您可以改为使用 setArrayValue(a, index, counter)

【讨论】:

以上是关于重载 operator() 在 Cython 中失败的主要内容,如果未能解决你的问题,请参考以下文章

即使我重载了`operator<<`,也不能在类中使用`cout`

重载 operator= 作为非成员 [重复]

操作符重载operator

void()、逗号运算符 (operator,) 和不可能的 (?) 重载

用 operator* 重载包装矩阵乘法

operator重载运算符