1

谁能解释为什么这个扩展会导致 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(关键点的向量),因为没有必要重现崩溃。

我构建了 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++(我将它构建为一个库,然后我用 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 错误吗?一个opencv错误?还是 C++ 错误?还是我做错了什么?我的编译器是 Visual Studio Express 2009

4

1 回答 1

0

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

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

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

我必须将 /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 构建

在那之后,我停止了崩溃。

于 2013-09-28T00:40:20.923 回答