从Python调用cpp函数时出现分段错误

从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

我正在尝试从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, 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
@eryksun
tessextrendercreate
的结果类型为
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最后一页的文本,而不是返回所有页面的文本。你见过这个吗?我在这里也提出了一个问题