使用指针在C++向量中的Cython

huangapple go评论53阅读模式
英文:

Using pointer to C++ vectors in Cython

问题

我正在尝试在Cython中定义指向C++向量的指针,并且我注意到了一个我无法用我的Cython知识解释的奇怪行为。下面,我创建了一个指向基于T范围的double向量的指针。我要么将a赋给a_low,要么赋给a_high

from libcpp.vector cimport vector

cdef vector[double] a_low = [1.0, 2e-03, -4e-07, 6.3e-10, -2.21e-5, -3.45e+01];
cdef vector[double] a_high = [-2.21e-01, 4.1e-03, -6.12e-02, 1.65e-09, -9.3e-6, -1.4e+02];

def h_calc(double T):
    cdef vector[double] *a
    cdef double h
    if (T < 1000.0):
        a = &a_low;
    else:
        a = &a_high;
    print(a[0])
    h = 0.0;
    return h;

执行h_calc(1200);输出[-0.221, 0.0041, -0.0612, 1.65e-09, -9.3e-06, -140.0],这是由于print(a[0])导致的。在这里,因为T > 1000,我们看到输出显示了a_high

我不理解的是为什么a[0]没有返回a_high向量的第一个值,而是整个向量?

英文:

I was trying define pointers to C++ vectors in Cython, and I noticed a strange behavior that I cannot explain with my Cython knowledge. Below, I have created a pointer to a vector of double based on T range. I either assign a to a_low or a_high.

from libcpp.vector cimport vector

cdef vector[double] a_low = [1.0, 2e-03, -4e-07, 6.3e-10, -2.21e-5, -3.45e+01];
cdef vector[double] a_high = [-2.21e-01, 4.1e-03, -6.12e-02, 1.65e-09, -9.3e-6, -1.4e+02];

def h_calc(double T):
    cdef vector[double] *a
    cdef double h
    if (T&lt;1000.0):
        a = &amp;a_low;
    else:
        a = &amp;a_high;
    print(a[0])
    h = 0.0;
    return h;

executing h_calc(1200); gives out [-0.221, 0.0041, -0.0612, 1.65e-09, -9.3e-06, -140.0] which results from print(a[0]). Here, because T&gt;1000, we see a_high was displayed as output.

What I don't understand is why a[0] does not return the first value of the vector a_high , but rather the whole vector?

答案1

得分: 2

在Cython中,解引用(即在C++中的*a)写作a[0],因为前者不是有效的Python语法,而后者是有效的。请参考这里的"Types"部分

也就是说,发生的情况是:

  • 您的a是类型为vector[double] *的指针,
  • a[0]是解引用版本(即仅为vector[double]类型),
  • print(a[0])vector[double]转换为Python列表并打印(即整个列表),
  • (这也是为什么a[1]会崩溃 - 实际上它在做*(a+1),并且导致内存违规)。

此外,值得一提的是,从Python列表赋值应该可以工作 - Cython会为您有效地将其重写为循环遍历Python列表,并在每个项上调用push_back(...)

英文:

In Cython dereferencing (i.e. *a in c++) is spelled as a[0] as the former is not valid python syntax while the latter is - see the "Types" section here

I.e. whats happening is:

  • your a is of type vector[double] *,
  • a[0] is the dereferenced version (i.e. just a vector[double])
  • print(a[0]) converts vector[double] to a python list and prints that (i.e. the whole list)
  • (this is also why a[1] crashes - it's effectively doing *(a+1), and getting a memory violation)

Also for what it's worth the assignment from the python list should work - Cython effectively rewrites it to loop over the python list calling push_back(...) on each item for you.

答案2

得分: 1

[] 是一个 PyObject。你不能将其分配给一个 C++ 类型(如 cdef 中所示)的 vector。转换不是隐式的。可能整个值字符串被视为第一个元素。当访问 a[1] 时会发生什么?

你必须声明这个 vector,并单独分配值给它。

cdef vector[double] a_low
a_low.push_back(1.0)
a_low.push_back(2e-03)
...

也许你还可以尝试使用 vector::insert (iterator position, const value_type& val);,它可以接受一个元素数组。同样,你必须传递一个 C 数组类型,所以你必须在传递之前声明并填充你的数组。

cdef double array[6]
array[:] = [1.0, 2e-03, -4e-07, 6.3e-10, -2.21e-5, -3.45e+01]

然后将其传递给 vector::insert。

正如你所看到的,你可以用一行代码填充一个 C 风格的数组,但不能填充一个 Cython 中的 vector。这引发了一个问题,为什么不直接在开始时使用数组呢?

英文:

[] is a PyObject. You can't assign it to a c++ type (as evidenced with cdef) of a vector. The conversion isn't implicit. Likely the whole string of values is being treated as the first element. What happens when you access a[1]?

You have to declare the vector, and assign the values to it separately.


cdef vector[double] a_low


a_low.push_back(1.0)
a_low.push_back(2e-03)
...

Perhaps you can also try experimenting with
vector::insert (iterator position, const value_type&amp; val);, which can take an array of elements. Again, you would have to pass it a c array type, so you would have to declare and fill your array before passing it.

cdef double array[6]

array[:] = [1.0, 2e-03, -4e-07, 6.3e-10, -2.21e-5, -3.45e+01] then pass it to vector::insert.

As you can see you can fill a C style array but not a vector in Cython in a one-liner. This raises the question, why not just use arrays in the first place?

huangapple
  • 本文由 发表于 2023年6月6日 03:55:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76409611.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定