Cython - 分配 C++ 类实例指针时的分段错误

cython - segmentation fault when assigning c++ class instance pointers

本文关键字:分段 错误 指针 实例 分配 C++ Cython      更新时间:2023-10-16

我是cython的新手,正在尝试用cython包装一些现有的c ++代码,以便它们可以在python中使用。我的问题的一个简化版本如下。

#ifndef A_H
#define A_H
class A
{
public:
    int value;
    A(int x);
    void printA();
};
#endif

答.cpp

#include <iostream>
#include "A.h"
A::A(int x)
{
    std::cout<<"entering A constructor"<<std::endl;
    value = x;
    std::cout<<"exiting A constructor"<<std::endl;
}
void A::printA()
{
    std::cout<<"print value in A :"<<value<<std::endl;
}

CMD.H

#include "A.h"
class CMD
{
public:
    A *a;
    void init(int x);
    void test();
};  

CMD.cpp

#include "cmd.h"
#include <iostream>
void CMD::init(int x)
{
    std::cout<<"start initializing A"<<std::endl;
    a = new A(x); // this line is causing the segmentation fault
    std::cout<<"end initializing A"<<std::endl;
}
void CMD::test()
{
    std::cout<<"start printing A"<<std::endl;
    a->printA();
    std::cout<<"end printing A"<<std::endl;
}

PyCMD.pyx

cdef extern from "cmd.h":
    # cdef cppclass A:
    #     A(int x)
    cdef cppclass CMD:
        # A *a
        CMD()
        void init(int x)
        void test()
cdef class PyCMD:
    cdef CMD *thisptr
    def __cint__(self):
        self.thisptr = new CMD()
    def __dealloc__(self):
        del self.thisptr
    def init(self, x):
        self.thisptr.init(x)
    def test(self):
        self.thisptr.test()

setup.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [Extension("cmdtest", ["PyCMD.pyx","cmd.cpp","A.cpp"],language='c++')]
)

helloword.py

from cmdtest import *
d = PyCMD()
d.init(10)
d.test()

该程序非常简单。类 A 只有一个构造函数和一个方法来打印 A 中的值.类 cmd 在其 init() 方法中创建 A 的实例,并在 test() 中调用 A 的 printA() 方法。cython代码基本上创建了一个cdef类PyCMD,它模仿cmd类中所有可用的方法。当我运行 helloworld.py 时,输出如下。

start initializing A
entering A constructor
exiting A constructor
[1]    11689 segmentation fault  {my_python_path}

显然,分段错误发生在分配 A 实例的指针时。然后我写了一个main.cpp以确保至少c++代码是可靠的。

主.cpp

#include "cmd.h"
int main()
{
    CMD *cmd = new CMD();
    cmd->init(10);
    cmd->test();
}

输出看起来不错。

start initializing A
entering A constructor
exiting A constructor
end initializing A
start printing A
print value in A :10
end printing A

问题应该出在cython上,但我不知道那在哪里。

我非常感谢任何帮助。

问题是你没有 PyCMD 的初始值设定项,所以thisptr是未初始化的。

可以看到,你只是在Cython代码中的任何位置打印出self.thisptr,或者在C++代码中打印出this

您确实有一个看起来像初始值设定项的函数...但因为它被称为__cint__而不是__cinit__,所以它不是。

因此,等效C++代码如下所示:

#include "cmd.h"
int main()
{
    CMD *cmd;
    cmd->init(10);
    cmd->test();
}

。这给出了完全相同的段错误。