2010-10-29 7 views
3

Il y a ce grand composant OCR open source que Google développe: http://code.google.com/p/tesseract-ocr/Delphi/Tesseract OCR: Quelqu'un peut-il m'aider à faire fonctionner cette nouvelle DLL en Delphi?

Ils ont une nouvelle version sur (version 3) au début d'Octobre 2010.

Mais cette nouvelle version ne a un wrapper C fonctionnel, et c'est à quelqu'un de la communauté Delphi de le faire fonctionner depuis Delphi - j'essaye de le faire parce que j'en ai vraiment besoin et personne d'autre n'est pressé de le faire mais j'ai aucune idée de ce que je fais quand il s'agit de DLL et de convertir C en Delphi. C'est là que je pourrais utiliser votre aide.

Les indices que j'ai ramassés sont que j'ai besoin de Dependency Walker pour empêcher d'une façon ou d'une autre le 'manquement de noms' (aucune idée de ce que cela signifie). Les méthodes API DLL réelles sont dans les fichiers C - et probablement les noms de fonctions DLL que vous voyez dans Dependency-Walker correspondent aux fonctions dans le fichier API.

Voici tout ce dont vous aurez besoin pour aider: Vous aurez besoin d'un dossier avec le tessdll.dll et le leptonlib.dll doit juste être là. Vous aurez besoin d'un sous-dossier appelé 'tessdata', et dans le dossier seront vos 'fichiers de données de langue' - [vérifier la page de téléchargements sur le site]

Voici l'installateur Windows juste pour que vous puissiez voir la DLL en action : [vérifiez la page de téléchargements sur le site]

Pour que cela fonctionne pour Delphi, vous aurez votre exécutable dans le même dossier que la DLL. Vous aurez besoin alors de savoir ce qu'il faut appeler la DLL, et que vous pouvez regarder dans les fichiers C Source: [vérifier les fichiers source sur la page de téléchargement sur le site]

Merci pour toute aide.

Répondre

6

Dès le premier regard cela pourrait être difficile. Comme l'API est apparemment encapsulée dans une classe C++, la seule façon de procéder est:

Implémentez une DLL wrapper en C qui expose une interface flattée de la classe afin que vous puissiez écrire une unité Delphi pour l'utiliser.

Le principe est décrit ici:

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

directement en utilisant l'API C++ nécessiterait quelques bidouillages assembleur intelligent. Ce n'est pas seulement le nom mangling qui est un problème ici, mais aussi la convention d'appel du compilateur C++ qui a été utilisé pour créer la DLL (qui est Visual Studio 2008 Express).

Ainsi, quelqu'un doit d'abord écrire une DLL avec une API C en utilisant Visual C++ 2008 Express.

Quelques précisions concering vos commentaires:

Lorsque vous souhaitez utiliser une bibliothèque externe dans votre application, vous devez savoir quels symboles vous devez importer.

Un symbole normal serait 'SetDllDirectory' dans kernel32.dll. Pas de problème pour importer cela dans Delphi, mais C++ utilise normalement un moyen plus artificiel pour nommer ses symboles.Un exemple serait '_ZN · 9wikipedia · 7article · 6format · E' (tiré de cet article: http://en.wikipedia.org/wiki/Name_mangling)

Bien qu'il soit possible d'importer un symbole mutilé qui n'est qu'une petite partie du problème.

Vous pouvez demander au compilateur C++ de ne pas utiliser la gestion des noms en utilisant la directive extern "C" {.

Il y a encore au moins deux problèmes supplémentaires:

  • Vous n'avez pas une méthode pour déterminer la taille d'un objet C++ exemple de Delphi
  • Toutes les méthodes d'un objet C++ prendre un this caché l'argument (comme Self dans Delphi)

Ces problèmes peuvent être contournés en écrivant un emballage comme expliqué dans l'article de Rudy.

Vous devez écrire simple C++ dll qui exporte une API C normal (sans mutiler et avec des fonctions normales C), en pseudo-code, il ressemble à ça:

extern "C" { 

void* MakeAnInstanceOfDesiredClass(void) 
{ 
    return new DesiredClass(); 
} 

void DestroyInstanceOfDesiredClass(void* instance) 
{ 
    delete instance; 
} 

int SomeMethodOfDesiredClass(void* instance) 
{ 
    return reinterpret_cast<DesiredClass*>(instance)->SomeMethod(); 
} 

} 

je lui donnerais un essai , mais ma connexion internet est assez lente et je n'ai pas Visual Studio ici, désolé.

+0

Merci pour cette réponse, elle apporte un peu de lumière. Cependant, je suis encore plutôt confus. J'ai téléchargé Visual C++ 2010 parce que je suis désespéré d'obtenir la version 3 - donc je pourrais aussi bien essayer de le faire moi-même - mais je suis complètement désemparé à ce sujet et encore très confus. Comme, est le code source dans quoi, C, C++? Puis-je compiler les deux langages à partir de Visual C++ 2010? Il existe une version "DLL Windows" de la DLL que vous pouvez télécharger - sûrement tout ce dont Delphi a besoin? ... Donc, d'après ce que vous dites, je n'ai aucune chance de me débrouiller comme un humble programmeur Delphi. –

+0

En outre, qu'est-ce que le 'mangling'? –

+0

Les DLL n'ont jamais été conçues pour exporter des méthodes d'objet. La gestion des noms contourne ce problème en utilisant un nom de fonction spécialement formaté. Les détails de la technique de mangling varie d'une langue à l'autre (et même d'un fabricant de compilateur à l'autre) Delphi utilise le nom mangling dans son format bpl (qui est un dll sous le capot). –

2

En fait, après avoir pris un coup d'oeil de plus près la documentation qu'il pourrait y avoir un sous-ensemble de la fonction qui sont encore API C et donc accessible directement à partir de 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) 

Je ne sais pas si ces fonctions sont assez, mais ils sont directement accessibles.

+0

en fait je crois que ces fonctions sont pour le wrapper pour la dernière version 2.04 et sont dépréciées dans cette nouvelle version 3.0. il y a un problème ouvert sur la page des problèmes du site en disant cela, et qu'un nouveau wrapper C doit être écrit pour la version 3.0. –

1

La conversion du code que Jens a cité ne devrait pas être trop difficile. Vous pouvez essayer un convertisseur C to Delphi (http://www.drbob42.com/delphi/headconv.htm, http://cc.embarcadero.com/item/26951). Méfiez-vous qu'ils peuvent seulement convertir 60-80% du code, donc le travail manuel suit. Si vous êtes toujours coincé après tout cela, recherchez si la conversion VB de l'en-tête existe. Il sera beaucoup plus facile que la conversion à partir de C, d'autant plus que le convertisseur VB2Delphi peut le faire probablement sans travail manuel après (http://www.marcocantu.com/tools/vb2delphi.htm).

Questions connexes