从Python调用cpp函数时出现分段错误
我正在尝试从python调用:从Python调用cpp函数时出现分段错误,python,c++,ctypes,tesseract,Python,C++,Ctypes,Tesseract,我正在尝试从python调用: TESS_API BOOL TESS_CALL TessBaseAPIProcessPages(TessBaseAPI* handle, const char* filename, const char* retry_config, int timeout_millisec, TessResultRenderer* renderer) { if (handle->ProcessPages(filename, retry_config, time
TESS_API BOOL TESS_CALL TessBaseAPIProcessPages(TessBaseAPI* handle, const char* filename,
const char* retry_config, int timeout_millisec, TessResultRenderer* renderer)
{
if (handle->ProcessPages(filename, retry_config, timeout_millisec, renderer))
return TRUE;
else
return FALSE;
}
此函数的最后一个参数是TessResultRenderer
。创建TessResultRenderer
TESS_API TessResultRenderer* TESS_CALL TessTextRendererCreate(const char* outputbase)
{
return new TessTextRenderer(outputbase);
}
现在,在从python调用此函数时,我执行了以下操作:
outputbase = "stdout"
renderer = tesseract.TessTextRendererCreate(outputbase)
text_out = tesseract.TessBaseAPIProcessPages(api,
ctypes.create_string_buffer(path),
None, 0, renderer) //Segmentation fault (core dumped) error on this line
但是我不断得到分段错误错误
我的问题是如何从Python调用TessBaseAPIProcessPages
代码库中还有一些参考链接:
编辑
在尝试注释建议后,我执行了以下操作,但出现了一个错误:_argtypes_中的项1没有from_param方法
PTessResultRenderer = ctypes.POINTER(TessResultRenderer)
self.tesseract.TessTextRendererCreate.restype = PTessResultRenderer
outputbase = "stdout"
self.tesseract.TessTextRendererCreate.argtypes = [outputbase] #error here
self.tesseract.TessTextRendererCreate
ReturnVal = ctypes.c_bool
self.tesseract.TessBaseAPIProcessPages.argtypes = [self.api, path, None, 0, PTessResultRenderer]
self.tesseract.TessBaseAPIProcessPages.restype = ReturnVal
self.tesseracto.TessBaseAPIProcessPages
class TessResultRenderer(ctypes.Structure):
pass
当数组溢出或取消引用空指针时,会发生分段错误。如果使用调试器,它将逐步完成所有代码,并准确显示正在进行的操作。这里有一个使用contrib文件夹中ctypes中的tesseract C-API的示例。然而,它似乎有点过时了
对于一些方法,您需要设置restype
和argtypes
。另外,不要忘记调用处理程序上的init函数。下面的例子对我很有用。它将英文名为“test.bmp”的文件中的文本读入text
变量
from ctypes import *
from ctypes.util import find_library
lang = b"eng"
filename = b"test.bmp"
TESSDATA_PREFIX = b"/usr/local/Cellar/tesseract/3.04.01_1/share/tessdata"
path = find_library("libtesseract.dylib")
tesseract = CDLL(path)
class TessBaseAPI(Structure):
pass
class TessResultRenderer(Structure):
pass
tesseract.TessBaseAPICreate.restype = POINTER(TessBaseAPI)
tesseract.TessBaseAPIInit3.argtypes = [POINTER(TessBaseAPI), c_char_p, c_char_p]
tesseract.TessBaseAPIInit3.restype = c_bool
tesseract.TessBaseAPIProcessPages.argtypes = [POINTER(TessBaseAPI), c_char_p, c_char_p, c_int, POINTER(TessResultRenderer)]
tesseract.TessBaseAPIProcessPages.restype = c_bool
tesseract.TessBaseAPIGetUTF8Text.argtypes = [POINTER(TessBaseAPI)]
tesseract.TessBaseAPIGetUTF8Text.restype = c_char_p
api = tesseract.TessBaseAPICreate()
rc = tesseract.TessBaseAPIInit3(api, TESSDATA_PREFIX, lang);
if (rc):
tesseract.TessBaseAPIDelete(api)
print("Could not initialize tesseract.\n")
exit(3)
success = tesseract.TessBaseAPIProcessPages(api, filename, None , 0, None)
if success:
text = tesseract.TessBaseAPIGetUTF8Text(api)
print("="*78)
print(text.decode("utf-8").strip())
print("="*78)
输出如下所示:
==============================================================================
This is a lot of 12 point text to test the
ocr code and see if it works on all types
of file format.
The quick brown dog jumped over the
lazy fox. The quick brown dog jumped
over the lazy fox. The quick brown dog
jumped over the lazy fox. The quick
brown dog jumped over the lazy fox.
==============================================================================
编辑:按照eryksun的建议,使用不透明类型替换了c\u void\u p
。谢谢 默认结果类型为c_int
。它也是整数参数的默认转换类型。了解如何设置restype
和argtypes
@eryksuntessextrendercreate
的结果类型为new tessextrenderer
。我知道argtypes,但不确定如何在此处应用它。请使用不透明类型:class-TessResultRenderer(ctypes.Structure):pass
。为其创建指针类型:PTessResultRenderer=ctypes.pointer(TessResultRenderer)
。然后设置tesseract.tessextrendercreate.restype=PTessResultRenderer
@eryksun我已经根据您的帮助编辑了这个问题。请您看一下……我仍然得到一个错误。argtypes
是指定参数的类型,而不是调用函数。例如:tesseract.tessertextrendercreate.argtypes=[ctypes.c_char_p]
和tesseract.TessBaseAPIProcessPages.argtypes=[PTessBaseAPI,ctypes.c_char_p,ctypes.c_char_p,ctypes.c_int,ptessResultrender]
c_void_p
起作用,但它不是类型安全的。您应该利用所有的工具为编程错误获取干净的Python异常,而不是用segfault使进程崩溃。你能整合我的建议来定义不透明类型吗?只需要几行代码就可以定义PTessBaseAPI
和PTessResultRenderer
来代替c\u void\u p
@eryksun直到阅读您的评论我才遇到不透明类型。谢谢你的启示@Snorfalorpagus谢谢!这对我很管用。另外,感谢您对tesseract回购协议中的相关问题发表评论。我打开了另一个问题,我从tesseract命令行和API中得到了不同的结果:你知道可能是什么导致了这种差异吗?@Snorfalorpagus我注意到使用TessBaseAPIProcessPages
只返回多页tiff最后一页的文本,而不是返回所有页面的文本。你见过这个吗?我在这里也提出了一个问题