【问题标题】:Delphi / Tesseract OCR: Can somebody help me get this new DLL working in Delphi? [closed]Delphi / Tesseract OCR:有人可以帮我让这个新的 DLL 在 Delphi 中工作吗? [关闭]
【发布时间】:2010-10-29 15:11:22
【问题描述】:

Google 一直在开发这个很棒的开源 OCR 组件: http://code.google.com/p/tesseract-ocr/

他们在 2010 年 10 月初推出了新版本(第 3 版)。

但是这个新版本不再有一个可以工作的 C 包装器,这取决于 Delphi 社区中的某个人来让它在 Delphi 内部工作——我正在尝试这样做,因为我非常需要它而没有其他人是急于做,但我不知道当涉及到 DLL 并将 C 转换为 Delphi 时我在做什么。这就是我可以使用您的帮助的地方。

我得到的线索是,我需要 Dependency Walker 以某种方式防止“名称篡改”(不知道这意味着什么)。 实际的 DLL API 方法位于 C 文件中 - 并且您在 Dependency-Walker 中看到的 DLL 函数名称可能与 API 文件中的函数匹配。

以下是您需要帮助的一切: 您将需要一个包含 tessdll.dll 的文件夹,并且 leptonlib.dll 也只需要在那里。您需要一个名为“tessdata”的子文件夹,该文件夹内将是您的“语言数据文件” - [查看网站上的下载页面]

这是 Windows 安装程序,您可以看到 DLL 的运行情况: [查看网站上的下载页面]

要让这个在 Delphi 中工作,您需要将可执行文件与 DLL 放在同一个文件夹中。 然后,您需要知道在 DLL 中调用什么,为此您可以查看 C 源文件: [查看网站下载页面上的源文件]

感谢您的帮助。

【问题讨论】:

    标签: delphi dll ocr tesseract


    【解决方案1】:

    乍一看,这可能很困难。由于 API 表面上封装在 C++ 类中,因此唯一干净的方法是:

    在 C 中实现一个包装 DLL,它公开类的扁平化接口,以便您可以编写一个 Delphi 单元来使用它。

    这里概述了原理:

    http://rvelthuis.de/articles/articles-cppobjs.html

    直接使用 C++ API 需要一些巧妙的汇编程序破解。这里的问题不仅在于名称修改,还在于用于创建 DLL 的 C++ 编译器的调用约定(即 Visual Studio 2008 Express)。

    所以有人必须首先使用 Visual C++ 2008 Express 编写一个带有 C API 的 DLL。

    关于您的 cmets 的一些说明:

    当您想在应用程序中使用外部库时,您需要知道需要导入哪些符号。

    kernel32.dll 中的正常符号是“SetDllDirectory”。在 Delphi 中导入它没有问题,但 C++ 通常使用更人为的方式来命名其符号。一个例子是'_ZN·9wikipedia·7article·6format·E'(摘自这篇文章:http://en.wikipedia.org/wiki/Name_mangling

    虽然可以导入损坏的符号,但这只是问题的一小部分。

    您可以使用 extern "C" { 指令告诉 C++ 编译器不要使用名称修饰。

    还有至少两个额外的问题:

    • 您没有从 Delphi 确定 C++ 对象实例大小的方法
    • C++ 对象的所有方法都采用隐藏的this 参数(如 Delphi 中的 Self)

    这些问题可以通过像 Rudy 的文章中解释的那样编写包装器来规避。

    你必须编写一个简单的 C++ Dll 来导出一个普通的 C API(没有修改和普通的 C 函数),在伪代码中它看起来像这样:

    extern "C" {
    
    void* MakeAnInstanceOfDesiredClass(void)
    {
        return new DesiredClass();
    }
    
    void DestroyInstanceOfDesiredClass(void* instance)
    {
        delete instance;
    }
    
    int SomeMethodOfDesiredClass(void* instance)
    {
        return reinterpret_cast<DesiredClass*>(instance)->SomeMethod();
    }
    
    }
    

    我会试一试,但我的互联网连接速度很慢,而且我这里没有 Visual Studio,抱歉。

    【讨论】:

    • 感谢您的回答,它确实提供了一些启示。但是,我仍然很困惑。我已经下载了 Visual C++ 2010,因为我很想获得第 3 版——所以我不妨自己尝试一下——但我对此一无所知,仍然很困惑。比如,源代码是什么,C,C++?我可以从 Visual C++ 2010 编译这两种语言吗?您可以下载 DLL 的“Windows DLL”版本——这就是 Delphi 所需要的吗? ...因此,根据您的说法,作为一个卑微的 Delphi 程序员,我自己没有机会做到这一点。
    • 另外,什么是'name mangling'?
    • Dll 从未设计用于导出对象方法。名称修改通过使用特殊格式的函数名称来解决此问题。修饰技术的细节因一种语言而异(甚至从一个编译器制造商到另一种语言),Delphi 在其 bpl 格式中使用名称修饰(它是一个底层的 dll)。
    • Mangling 也用于静态库。
    【解决方案2】:

    实际上,在仔细查看文档之后,可能有一部分函数仍然是 C API,因此可以直接从 Delphi 访问:

    BOOL APIENTRY  DllMain (HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 
    TESSDLL_API void __cdecl  TessDllRelease () 
    TESSDLL_API void *__cdecl  TessDllInit (const char *lang) 
    TESSDLL_API int __cdecl  TessDllBeginPageBPP (uinT32 xsize, uinT32 ysize, unsigned char *buf, uinT8 bpp) 
    TESSDLL_API int __cdecl  TessDllBeginPageLangBPP (uinT32 xsize, uinT32 ysize, unsigned char *buf, const char *lang, uinT8 bpp) 
    TESSDLL_API int __cdecl  TessDllBeginPageUprightBPP (uinT32 xsize, uinT32 ysize, unsigned char *buf, const char *lang, uinT8 bpp) 
    TESSDLL_API int __cdecl  TessDllBeginPage (uinT32 xsize, uinT32 ysize, unsigned char *buf) 
    TESSDLL_API int __cdecl  TessDllBeginPageLang (uinT32 xsize, uinT32 ysize, unsigned char *buf, const char *lang) 
    TESSDLL_API int __cdecl  TessDllBeginPageUpright (uinT32 xsize, uinT32 ysize, unsigned char *buf, const char *lang) 
    TESSDLL_API void __cdecl  TessDllEndPage (void) 
    TESSDLL_API ETEXT_DESC *__cdecl  TessDllRecognize_a_Block (uinT32 left, uinT32 right, uinT32 top, uinT32 bottom) 
    TESSDLL_API ETEXT_DESC *__cdecl  TessDllRecognize_all_Words (void) 
    TESSDLL_API void __cdecl  ReleaseRecognize () 
    TESSDLL_API void *__cdecl  InitRecognize () 
    TESSDLL_API int __cdecl  CreateRecognize (uinT32 xsize, uinT32 ysize, unsigned char *buf) 
    TESSDLL_API ETEXT_DESC *__cdecl  reconize_a_word (uinT32 left, uinT32 right, uinT32 top, uinT32 bottom) 
    

    不知道这些功能够不够用,但都可以直接访问。

    【讨论】:

    • 实际上我相信这些函数是用于最后一个版本 2.04 的包装器,并在这个新版本 3.0 中被弃用。在网站的问题页面上打开了一个问题,说明了这一点,并且必须为 3.0 版编写新的 C 包装器。
    【解决方案3】:

    转换 Jens 引用的代码应该不会太难。您可以尝试一些 C 到 Delphi 转换器(http://www.drbob42.com/delphi/headconv.htm,http://cc.embarcadero.com/item/26951)。请注意,他们只能转换 60-80% 的代码,因此需要手动操作。如果你在这一切之后仍然卡住,那么搜索是否存在标题的VB转换。它会比从 C 转换容易得多,特别是因为 VB2Delphi 转换器可以做到这一点,之后可能无需手动工作(http://www.marcocantu.com/tools/vb2delphi.htm)。

    【讨论】:

      猜你喜欢
      • 2022-06-14
      • 2013-05-17
      • 1970-01-01
      • 2021-08-12
      • 1970-01-01
      • 1970-01-01
      • 2021-01-04
      • 2022-07-07
      • 1970-01-01
      相关资源
      最近更新 更多