OpenCV 在通过 Python ctype 使用时在共享库中调用段错误
opencv calls in shared library segfaults when used through python ctypes
每当我使用 ctypes 将共享库 (.so) 加载到 Python 中并调用其中一个使用 OpenCV 过滤器引擎(如 cvErode 或 cvDilate)的过程时,解释器都会在 OpenCV 代码深处出现段错误。如果我在 C 程序中使用 dlopen 加载相同的库并调用相同的过程,一切正常。
我在另一篇文章中读到,它可能与 gcc 使用的 ABI 有关,并且 python 必须使用与 python 解释器编译的相同版本的 gcc 进行编译才能正常工作。但是就我而言,它都是 4.4.5,所以这应该不是问题。OpenCV库也是用相同版本的gcc编译的。
共享库的构建方式:
g++ -g -shared -lopencv_core -lopencv_imgproc -lopencv_calib3d -lopencv_video -lopencv_features2d -lopencv_ml -lopencv_highgui -lopencv_objdetect -lopencv_contrib -lopencv_legacy -o thumbsplit.so thumbsplit.cpp
如何包装共享库:
extern "C" {
int is_thumbsheet(char * image_path){
Image image;
image.read(image_path);
int width = image.columns();
int height = image.rows();
int BOUND_CHANGE = 7000;
int test_height = 0;
if( width > height ){
return 0;
}else{
test_height = width;
}
vector<int> test_rows = getRows(image, width, test_height, BOUND_CHANGE);
vector<int> test_cols = getCols(image, width, test_height, BOUND_CHANGE);
vector<Box> test_boxes = createBoxes(test_rows,test_cols,width,height);
if( test_boxes.size() > 6 ){
return 1;
}else{
return 0;
}
}
int cut_thumbs(char * image_path, char * thumb_path){
Image image;
image.read(image_path);
int width = image.columns();
int height = image.rows();
int BOUND_CHANGE = 7000;
vector<int> rows = getRows(image, width, height, BOUND_CHANGE);
vector<int> cols = getCols(image, width, height, BOUND_CHANGE);
//drawDebugLines(rows, cols, width, height);
vector<Box> boxes = createBoxes(rows,cols,width,height);
//printBoxes(boxes);
char path[0x100];
for( int i=0 ; i < boxes.size() ; i++ ){
sprintf(path, "%s%d.jpg", thumb_path, i);
boxes[i].saveBox(image, path);
}
return 0;
}
} // C
如何在 python 中加载共享库过程:
import ctypes, os
def load_lib():
lib_path = "%s/%s"%(os.path.realpath(os.path.dirname(__file__)), "thumbsplit.so")
lib = ctypes.CDLL(lib_path)
return lib
def is_thumbsheet(image_path):
lib = load_lib()
if lib.is_thumbsheet(image_path):
return True
else:
return False
def cut_thumbs(image_path, thumbs_path):
lib = load_lib()
lib.cut_thumbs(image_path, thumbs_path)
is_thumbsheet("/home/rolf/test/imageproc/full9.jpg") # this segfaults
GDB 输出:
$ gdb python
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/bin/python...(no debugging symbols found)...done.
(gdb) run thumbsheet.py
Starting program: /usr/bin/python thumbsheet.py
[Thread debugging using libthread_db enabled]
0xb6330a12
Program received signal SIGSEGV, Segmentation fault.
0xb76fe2dc in cv::FilterEngine::start(cv::Size_<int>, cv::Rect_<int>, int) () from /usr/local/lib/libopencv_imgproc.so.2.3
(gdb) info stack
#0 0xb76fe2dc in cv::FilterEngine::start(cv::Size_<int>, cv::Rect_<int>, int) () from /usr/local/lib/libopencv_imgproc.so.2.3
#1 0xb76feb41 in cv::FilterEngine::start(cv::Mat const&, cv::Rect_<int> const&, bool, int) ()
from /usr/local/lib/libopencv_imgproc.so.2.3
#2 0xb770a52b in cv::FilterEngine::apply(cv::Mat const&, cv::Mat&, cv::Rect_<int> const&, cv::Point_<int>, bool) ()
from /usr/local/lib/libopencv_imgproc.so.2.3
#3 0xb764bf8a in cv::morphOp(int, cv::_InputArray const&, cv::_OutputArray const&, cv::_InputArray const&, cv::Point_<int>, int, int, cv::Scalar_<double> const&) () from /usr/local/lib/libopencv_imgproc.so.2.3
#4 0xb764d2ce in cv::erode(cv::_InputArray const&, cv::_OutputArray const&, cv::_InputArray const&, cv::Point_<int>, int, int, cv::Scalar_<double> const&) () from /usr/local/lib/libopencv_imgproc.so.2.3
#5 0xb764d62e in cvErode () from /usr/local/lib/libopencv_imgproc.so.2.3
#6 0xb7fd7adb in seperate::findSeperatedBoxes (img=0x8351d70) at seperate.cpp:189
#7 0xb7fd7fcf in seperate::trySeperatedBoxes (img=0x8351d70, percentage_boxed=0xbfffefec) at seperate.cpp:202
#8 0xb7fda00c in is_thumbsheet (image_path=0xb7c1bf74 "/home/rolf/test/imageproc/full9.jpg") at thumbsplit.cpp:39
#9 0xb7a047df in ffi_call_SYSV () from /usr/lib/python2.6/lib-dynload/_ctypes.so
#10 0xb7a0461e in ffi_call () from /usr/lib/python2.6/lib-dynload/_ctypes.so
#11 0xb79ff27d in _CallProc () from /usr/lib/python2.6/lib-dynload/_ctypes.so
#12 0xb79f6d7e in ?? () from /usr/lib/python2.6/lib-dynload/_ctypes.so
#13 0x0806232a in PyObject_Call ()
#14 0x080e016b in PyEval_EvalFrameEx ()
#15 0x080e18b0 in PyEval_EvalFrameEx ()
#16 0x080e2507 in PyEval_EvalCodeEx ()
#17 0x080e2607 in PyEval_EvalCode ()
#18 0x080ffcbd in PyRun_FileExFlags ()
#19 0x080fff22 in PyRun_SimpleFileExFlags ()
#20 0x0805dd81 in Py_Main ()
#21 0x0805cf6b in main ()
(gdb) x/i 0xb76fe2dc
0xb76fe2dc <_ZN2cv12FilterEngine5startENS_5Size_IiEENS_5Rect_IiEEi+1212>: movdqa %xmm3,0x30(%esp)
(gdb)
GCC/G++ 版本:
$ python
Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
[GCC 4.4.5] on linux2
$ gcc --version
gcc (Debian 4.4.5-8) 4.4.5
$ g++ --version
g++ (Debian 4.4.5-8) 4.4.5
OpenCV 是 2.3.1 版本,是使用此版本的 gcc (4.4.5-8) 从源代码构建的
我已经找到了解决方案。对于 SSE 指令,堆栈需要重新对齐为 16 个字节。如果我使用 -mstackrealign 构建共享库,它可以完美地加载并从 python 调用。
Qt、GCC、SSE 和堆栈对齐
相关文章:
- 为什么PyImport_ImportModule python 3.7.2 中出现段错误?
- 为什么在访问 vtkRenderWindow 的"交互器"变量时会发生段错误?
- 注册对对象工厂的调用会导致段错误
- 调用 pthread_create() C++ Linux 时的段错误
- 任何 GraphAttributes 函数调用上的 OGDF 段错误
- 节点.JS,C++模块:为什么当我尝试调用本地的长度方法时出现段错误<Array>?
- 调用TTF_OpenFont时出现奇怪的段错误
- 调用getlazybitcodemodule时出现段错误
- 'PyCObject_Import(“cairo”,“CAPI”)“C++调用产生段错误,”import Cai
- 为什么在成员函数调用上没有段错误
- OpenCV 在通过 Python ctype 使用时在共享库中调用段错误
- 为什么这段代码在w.show()调用上出现段错误?
- 调用函数指针会导致段错误
- 函数调用时的 PyObject 段错误
- 在c++中,指纹调用会导致段错误
- 调用派生类的虚函数时出现段错误
- 函数调用中的段错误
- 调用类构造函数会导致段错误(c++)
- 在联接线程上调用pthread_cancel会导致 Linux 下的段错误
- C++调用getenv("LINES")或getenv("COLUMNS")在Xcode中运行良好,在终端中运行时会出现段错误