奇怪的Cython扩展崩溃,cython错误

weird cython extension crash, cython bug?

本文关键字:cython 错误 崩溃 扩展 Cython      更新时间:2023-10-16

>谁能解释为什么这个扩展会崩溃python?
我已经为此疯狂了很多小时,我无法解释。

我简化了我的代码,以便它只显示重现崩溃所需的行:

我在"test_class.h"中有一个非常简单的C++类,它使用了几个opencv类型cv::Mat和cv::KeyPoint:

class TestClass
{
public:
    TestClass();
    cv::Mat& get_current_frame_descriptors();
    std::vector<cv::KeyPoint> _current_frame_points;
    cv::Mat _current_frame_descriptors;
};

"test_class.cpp">

TestClass::TestClass()
{
}
Mat& TestClass::get_current_frame_descriptors()
{
    return _current_frame_descriptors;
}

然后我在"test_class.pyx"中有一个cython包装器:

 from libcpp.vector cimport vector
 cdef extern from "opencv2/core/core.hpp" namespace "cv":
    cdef cppclass Mat:
        Mat()
        int dims, rows, cols, flags
cdef extern from "test_class.h":       
    cdef cppclass TClass "TestClass":
        TClass()
        Mat _current_frame_descriptors        
        Mat& get_current_frame_descriptors()

cdef class TestClass:
    cdef TClass *TClass_ptr
    def __cinit__(self):
        self.TClass_ptr = new TClass()
    def get_descriptors1(self):
        m = self.TClass_ptr.get_current_frame_descriptors()
        print m.dims
        print m.rows
        print m.cols
        print m.flags
    def get_descriptors2(self):
        m = self.TClass_ptr._current_frame_descriptors
        print m.dims
        print m.rows
        print m.cols
        print m.flags

请注意,TClass 不会声明_current_frame_points(KeyPoint 的向量(,因为没有必要重现崩溃。

我构建了cython扩展并对其进行了测试:

>>>import  test_class
>>>m = test_class.TestClass()

opencv Mat _current_frame_descriptors 是空的,因此变暗、行和列为零:

>>>m.get_descriptors1() 
0
0
0
1124007936
>>>m.get_descriptors2() 

这会使python崩溃!!

现在,如果我在 test_class.h 中反转 _current_frame_descriptors 和 _current_frame_points 的声明,那么我不会崩溃!!!

class TestClass
{
public:
    TestClass();
    cv::Mat& get_current_frame_descriptors();
    cv::Mat _current_frame_descriptors;
    std::vector<cv::KeyPoint> _current_frame_points;    
};

现在我重建C++(我将其构建为一个库,然后我链接到cython扩展(我重建cython扩展并对其进行测试

>>>import  test_class
>>>m = test_class.TestClass()

opencv 垫子_current_frame_descriptors是空的,所以当我这样做时

>>>m.get_descriptors1() 
0
0
0
1124007936
>>>m.get_descriptors2() 
0
0
0
1124007936

现在我得到了正确的结果!!

这怎么可能?这是一个cython错误吗?一个OpenCV错误?还是一个C++错误?还是我做错了什么?我的编译器是Visual Studio Express 2009

我找到了问题的原因。没有错误。这是我的问题。我正在混合运行时库:-(一个月前,我开始翻译一些数字python代码,以C++使用cython作为连接来验证一致的结果。当我构建cython扩展时,我用来获取此链接器警告:

链接:警告LNK4098:defaultlib 'MSVCRTD' 与其他库的使用冲突;使用/NODEFAULTLIB:Library

但是我不知道如何删除它,并且代码似乎有效。我实际上在这种情况下翻译了相当多的代码,直到现在我都没有问题。中间加几个星期的休息时间,我已经完全忘记了这件事。

我必须将/MDd 添加到extra_compile_args以匹配我的C++库。然后我会遇到我需要的问题python27_d.exe 一旦我尝试构建它,但随后我还必须构建我使用的每个库的调试版本!行不通!

我在如何在Windows上调试Python的C扩展中找到了一个技巧我不得不在 C:\Python27\include\pyconfig.h 中 #define Py_DEBUG 注释,然后将 python27.exe 复制到python27_d.exe现在我可以使用/MDd 进行构建

在那之后,我不再崩溃了。