3

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 源文件:[查看网站下载页面上的源文件]

感谢您的任何帮助。

4

3 回答 3

6

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

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

这里概述了原理:

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

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

因此,必须首先使用 Visual C++ 2008 Express 编写带有 C API 的 DLL。

关于您的评论的一些澄清:

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

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,抱歉。

于 2010-10-29T15:57:50.720 回答
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) 

我不知道这些功能是否足够,但它们可以直接访问。

于 2010-10-29T18:18:41.770 回答
1

转换 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)。

于 2010-11-01T10:43:18.453 回答