从 cython 直接调用 C++ 结构构造函数

Fak*_*ame 5 python struct cython

我正在尝试包装一些使用带有构造函数的结构的 C++ 代码,但不知道如何包装。

C++结构:

typedef struct point_3d_t
{
    double x;
    double y;
    double z;

    point_3d_t(double x, double y, double z)
        : x(x)
        , y(y)
        , z(z)
        {}

} point_3d;
Run Code Online (Sandbox Code Playgroud)

Cython 包装器:

cdef extern from "./cppdar.hpp":
    ctypedef struct point_3d:
        point_3d(double, double, double)
        double x;
        double y;
        double z;
Run Code Online (Sandbox Code Playgroud)

现在,我希望能够通过类似的方式cdef point_3d p1(v, v, v)(从 cython 文件中)构造结构,但我似乎无法弄清楚如何让 cython 仅使用提供的构造函数。

我试过了:

  • cdef point_3d p1(v, v, v)
  • cdef point_3d p1 = point_3d(v, v, v)
  • cdef point_3d p1(0, 0, 0)
  • cdef point_3d p1 = point_3d(0, 0, 0)

哪里v是明确的cdef double v = 0,但没有工作。

使用 plain cdef point_3d p1p1.x = nnnn等...,但这很烦人,而且我认为我不明白为什么我不应该使用默认构造函数。

尝试研究这个问题会产生很多与类构造函数相关的混乱,这没有帮助。

Fak*_*ame 3

好吧,答案是你不能在 cython 中使用构造函数参数堆栈分配 C++ 对象,基本上根本无法

来自: https: //groups.google.com/forum/#!topic /cython-users/fuKd-nQLpBs

是的,这是一个限制,但它是一个比解析器更基本的问题。C++ 中堆栈分配对象的构造和销毁与其作用域密切相关,并且 Python 和 C 中的作用域规则不同。例如,考虑

if some_condition(): 
    x = Foo(1) 
else: 
    x = Foo(2, 3) 
return x.method() 
Run Code Online (Sandbox Code Playgroud)

这根本无法用 C++ 来表达。反过来

if (some_other_condition()) { 
    Foo_with_RIAA foo(x) 
} 
... 
Run Code Online (Sandbox Code Playgroud)

不会“正确”翻译 Python 作用域规则。

现在在某些情况下它可能是有意义的,但必须进行重大的代码生成更改,因为目前所有变量都在函数顶部声明(遵循 C89 标准,一些编译器强制执行)但在 C++ 模式下我们必须将变量的声明推迟到其实例化(包括避免任何自动插入的 C 级 {} 作用域,以简化代码生成)。

由于人们总是可以在堆上分配如此复杂的对象,因此这并不是一个重大限制。

这是额外的加倍烦人,因为这意味着在许多情况下你根本无法包装缺少默认构造函数的类。


可怕的、不好的解决方法是将构造函数包装在一个简单的 C(++) 函数中,然后通过 cython 公开