奇怪的cython扩展崩溃,cython bug?

时间:2013-09-27 13:26:34

标签: c++ python opencv cython

有人可以解释为什么这个扩展会崩溃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(KeyPoints的向量),因为没有必要重现崩溃。

我构建了cython扩展,我测试了它:

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

opencv Mat _current_frame_descriptors为空,因此dims,rows和cols为零:

>>>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 ++(我将它构建为一个lib,然后我链接到cython扩展)我重建了cython扩展并测试它

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

opencv Mat _current_frame_descriptors为空,所以当我做

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

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

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

这怎么可能?这是一个cython bug吗?一个opencv bug?还是一个C ++错误?或者我做错了什么? 我的编译器是visual studio express 2009

1 个答案:

答案 0 :(得分:0)

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

LINK:警告LNK4098:defaultlib'MSVCRTD'与使用其他lib冲突;使用/ NODEFAULTLIB:库

但我不知道如何删除它,代码似乎工作。我实际上在这种情况下翻译了相当多的代码,直到现在我才遇到问题。在中间加几个休息时间,我完全忘了这个。

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

我在How to debug C extensions for Python on Windows找到了一个技巧 我不得不在C:\ Python27 \ include \ pyconfig.h中注释#define Py_DEBUG然后将python27.exe复制到python27_d.exe 现在我可以用/ MDd构建

之后我停止了崩溃。