[C++] gebruik van DLL library

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
In mijn C++ applicatie zou ik graag gebruik maken van de OCR software in Microsoft Office Document Imaging (MODI). Nu is dit kinderlijk eenvoudig in C#, door simpelweg de reference MODI 12.0 Type Library aan je project toe te voegen. Vervolgens is het slechts een kwestie van een paar regeltjes code:

C#:
1
2
3
4
5
6
7
8
string OCR(string filename)
{
    MODI.Document md = new MODI.Document();
    md.Create(filename);
    md.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, true, true);
    MODI.Image image = (MODI.Image)md.Images[0];
    return image.Layout.Text;
}


Volgens Microsoft zou dit ook mogelijk moeten zijn in C++:
A programmer can use a number of different programming languages, for example Visual Basic, C++, or VBScript, to manipulate these objects by invoking methods on the object or by getting and setting the object's properties.
Helaas is het voor mij een groot raadsel hoe ik dit precies zou moeten doen, omdat deze library volgens mij in de MDIVWCTL.DLL zit en er verder geen lib en header files zijn om te includen.

Na wat zoeken op het internet ben ik een aantal potentiele oplossingen tegen gekomen:Alle drie de opties zijn niet echt eenvoudig en vereisen een hoop geknutsel, enerzijds een MFC Application bij de eerste twee opties en anderzijds low level code waarbij je zelf de nodige functies moet definieren. Het werkend krijgen van deze oplossingen is verre van triviaal. Tevens vind ik het niet echt mooie oplossingen (code technisch gezien) en dat verwacht ik eigenlijk wel op basis van bovenstaande quote.

Een van mijn belangrijkste eisen is dat de code zoveel mogelijk platform onafhankelijk blijft. Uiteraard besef ik dat het gebruik van de OCR software in MODI tegenstrijdig is, echter is het idee dat dit als losstaand component in mijn code past en zo in de toekomst (indien gewenst) makkelijk te vervangen is door een ander (platform onafhankelijk) alternatief.

Mijn huidige oplossing is een simpele system call naar een C# applicatie met als parameters de locatie van een afbeelding en een locatie voor de output. Dit is natuurlijk ook niet erg mooi en bovendien heeft dit een efficientie probleem tot gevolg, doordat ik me bezig hou met tekst herkenning in videos en daardoor elke afbeelding (frame) eerst van het geheugen weg moet schrijven naar een bestand. Dit veroorzaakt een hoop I/O overhead, wat het gehele systeem significant veel trager maakt. Al moet ik toegeven dat ik ook nog niet direct een oplossing heb gevonden dit efficientie probleem te omzeilen in C#. Misschien is dit zelfs wel onmogelijk erg lastig.

De vraag is nu: Hoe zouden jullie dit oplossen? Zie ik misschien iets over het hoofd?

Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 21:30

Sebazzz

3dp

Wat jij dus voorstelt is om in C# een library te maken waarin je een paar methodes aanroept in je OCR library, en dat in een C++ applicatie die C# library gaat gebruiken? Dat is niet onmogelijk, maar wel moeilijker dan simpelweg linken.

Waarom maak je niet de hele applicatie in C#, of hoogstens het gedeelte wat de OCR doet en verwerkt? De overhead van de .NET runtime is tegenwoordig niet significant (immers, het WP7 platform is puur .NET, en dat is nog een mobiel platform ook). Eventueel zou je met de native assembly generator het één en ander nog kunnen accelereren.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
De kans dat een serieuze Microsoft library als deze een C# library is, is te verwaarlozen. Ook de hele procedurebeschrijving ("reference MODI 12.0 Type Library) klinkt als een COM library.

Wat betreft de linkjes van de TS, ik denk niet dat C++ geschikt voor je is, als je "#include "mdivwctl.h" " of "CoInitialize(0);" als complexe statements ziet.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22:35
De overhead van de .NET runtime is tegenwoordig niet significant (immers, het WP7 platform is puur .NET, en dat is nog een mobiel platform ook).
Omdat het Windows Phone 7 platform puur .NET is, is de overhead niet significant?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 21:30

Sebazzz

3dp

farlane schreef op maandag 23 augustus 2010 @ 09:47:
[...]


Omdat het Windows Phone 7 platform puur .NET is, is de overhead niet significant?
Als er een significante overhead was, dan had men geen managed runtime gekozen als de enige methode om applicaties te maken in WP7. Overigens zijn de runtimes zelf niet honderd procent te vergelijken, maar voor volledige versie op de desktop geldt hetzelfde.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 20:38

alienfruit

the alien you never expected

Het klinkt als een COM object (Type Library) als de library zelf niet een .net assembly is kan je toch makkelijk zelf de headers genereren? Zo uit het hoofd kan je hiervoor de COM/OLE Viewer van Visual Studio gebruiken om deze headers te genereren.

Maar goed, ik blijf er bij dat COM objecten maken of gebruiken één grote hel is (vast te dom)

Acties:
  • 0 Henk 'm!

  • Killemov
  • Registratie: Januari 2000
  • Laatst online: 24-08 23:40

Killemov

Ik zoek nog een mooi icooi =)

alienfruit schreef op maandag 23 augustus 2010 @ 09:53:
Het klinkt als een COM object (Type Library) als de library zelf niet een .net assembly is kan je toch makkelijk zelf de headers genereren? Zo uit het hoofd kan je hiervoor de COM/OLE Viewer van Visual Studio gebruiken om deze headers te genereren.

Maar goed, ik blijf er bij dat COM objecten maken of gebruiken één grote hel is (vast te dom)
Ik heb het werken met COM (en varianten) ook nooit als gemakkelijk ervaren hoor. Zelf COM objecten/libraries gemaakt in Delphi die anderen dan weer moesten gebruiken in Visual Basic. En dat is toch altijd lastig gebleven.

Hier moet vast wel iets nuttigs tussen zitten: http://www.google.nl/search?q=generate+header+from+com+dll

Hey ... maar dan heb je ook wat!


Acties:
  • 0 Henk 'm!

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 20:38

alienfruit

the alien you never expected

Ja, ik had precies hetzelfde probleem Delphi en C++ of VB. Drama, de verschillende thread models etc.

Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
Sebazzz schreef op maandag 23 augustus 2010 @ 09:31:
Wat jij dus voorstelt is om in C# een library te maken waarin je een paar methodes aanroept in je OCR library, en dat in een C++ applicatie die C# library gaat gebruiken? Dat is niet onmogelijk, maar wel moeilijker dan simpelweg linken.

Waarom maak je niet de hele applicatie in C#, of hoogstens het gedeelte wat de OCR doet en verwerkt? De overhead van de .NET runtime is tegenwoordig niet significant (immers, het WP7 platform is puur .NET, en dat is nog een mobiel platform ook). Eventueel zou je met de native assembly generator het één en ander nog kunnen accelereren.
Nee, het liefst zou ik simpelweg linken, maar het is me niet duidelijk hoe ik dit zou moeten doen. Ik maak de applicatie in c++, omdat vrijwel alle libraries die ik gebruik hiervoor geschreven zijn. Tevens wil ik de mogelijkheid hebben om in de toekomst de software geschikt te maken om te draaien op computer clusters (die dus linux draaien).
MSalters schreef op maandag 23 augustus 2010 @ 09:43:
De kans dat een serieuze Microsoft library als deze een C# library is, is te verwaarlozen. Ook de hele procedurebeschrijving ("reference MODI 12.0 Type Library) klinkt als een COM library.

Wat betreft de linkjes van de TS, ik denk niet dat C++ geschikt voor je is, als je "#include "mdivwctl.h" " of "CoInitialize(0);" als complexe statements ziet.
Het probleem zijn echt niet deze statements, maar eerder het feit dat het gebruik van deze library een MFC applicatie vereist die vervolgens een hoop 'lelijke' header files genereert en de naamgeving aanpast. Tevens is het mij niet gelukt om de 'mdivwctl.h' te vinden/genereren.
alienfruit schreef op maandag 23 augustus 2010 @ 09:53:
Het klinkt als een COM object (Type Library) als de library zelf niet een .net assembly is kan je toch makkelijk zelf de headers genereren? Zo uit het hoofd kan je hiervoor de COM/OLE Viewer van Visual Studio gebruiken om deze headers te genereren.

Maar goed, ik blijf er bij dat COM objecten maken of gebruiken één grote hel is (vast te dom)
Het is idd een COM object.
Killemov schreef op maandag 23 augustus 2010 @ 10:23:
[...]

Ik heb het werken met COM (en varianten) ook nooit als gemakkelijk ervaren hoor. Zelf COM objecten/libraries gemaakt in Delphi die anderen dan weer moesten gebruiken in Visual Basic. En dat is toch altijd lastig gebleven.

Hier moet vast wel iets nuttigs tussen zitten: http://www.google.nl/search?q=generate+header+from+com+dll
Goed om te lezen dat ik dus niet de enige ben die dit een drama vindt. Als ik het goed begrijp zou ik dus zowel een header als een lib file moeten genereren op basis van deze dll, waarna ik deze vervolgens simpelweg kan includen.

Acties:
  • 0 Henk 'm!

  • ZaZ
  • Registratie: Oktober 2002
  • Laatst online: 19-08 14:24

ZaZ

Tweakers abonnee

Gewoon googlen op use COM object c++ of iets dergelijks. Zo moeilijk is het nou ook weer niet. Helemaal niet als het geen grafisch component is maar slechts een lib.
COM objecten gebruiken is lang niet zo spannend als ze moeten schrijven. En met een klein beetje moeite hoef je het niet eens te registreren om het te gebruiken als het een lib is.

Lekker op de bank


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22:35
Sebazzz schreef op maandag 23 augustus 2010 @ 09:51:
[...]

Als er een significante overhead was, dan had men geen managed runtime gekozen als de enige methode om applicaties te maken in WP7. Overigens zijn de runtimes zelf niet honderd procent te vergelijken, maar voor volledige versie op de desktop geldt hetzelfde.
Ik ben bang dat performance niet de enige drijfveer was wat dat betreft.

Nu is de term 'significante overhead' wel enigzins rekbaar natuurlijk; (veel?) mensen hebben geen problemen met het inleveren van performance als ze daardoor een .NET enabled platform kunnen draaien.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 20:38

alienfruit

the alien you never expected

Bij mijn weten kan de OLE/COM Viewer applicatie gewoon alle benodigde files genereren...

Acties:
  • 0 Henk 'm!

  • jmzeeman
  • Registratie: April 2007
  • Laatst online: 12-09 16:17
Andere oplossing (misschien niet de netste) is om c++/cli (.NET in C++) te gebruiken je kan dan al je C++ libs gewoon gebruiken en een RCW maken voor de COM library hiervoor gebruik je tlbimp (dat is hetzelfde als wat visual studio voor C# onderwater gebruikt). (Nu ik het zeg mischien doet ie dat voor C++/cli ook wel gewoon automatisch als je een COM object include). Voordeel hiervan is dat de code vervolgens vrijwel exact het zelfde zal zijn als die voor C# (met toevoeging van een ^ hier en gcnew daar en hier en daar het vervangen van . door ->).

Je zegt ook dat je het op linux wil draaien, dan lijkt het me dat het gebruik van een COM object of DLL uberhaupt niet zo slim is, in dat geval lijkt het me slimmer om meteen naar een OS alternatief te gaan zoeken. Ten zij je mono/wine wil gebruiken in linux maar dan is het gebruik van .NET en MFC ook geen probleem.

[ Voor 10% gewijzigd door jmzeeman op 23-08-2010 20:45 ]


Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
Bedankt voor alle reacties, ik kan voorlopig wel even vooruit, helaas nog geen tijd gehad om de suggesties uit te proberen (hopelijk kom ik daar vanavond aan toe).
Je zegt ook dat je het op linux wil draaien, dan lijkt het me dat het gebruik van een COM object of DLL uberhaupt niet zo slim is, in dat geval lijkt het me slimmer om meteen naar een OS alternatief te gaan zoeken. Ten zij je mono/wine wil gebruiken in linux maar dan is het gebruik van .NET en MFC ook geen probleem.
Klopt, maar de performance van het OCR onderdeel is vrij belangrijk en het is een kleine stap om er later een ander alternatief in te hangen. De OCR in MODI is afkomstig van [url=http://www.nuance.com/]Nuance[/ur] en zij bieden ook een SDK aan. Echter moet je hier een paar duizend dollar voor neertellen en dat is iets wat in de ontwikkel fase nog niet nodig is, immers ga je tijdens het ontwikkelen nog niet terabytes aan data er doorheen pompen. Het idee is dus om eerst een werkend systeem te krijgen en later dus het OCR component te vervangen, aangezien dit toch maar een klein onderdeel van het systeem is.

Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
Wat ik nu gedaan heb is het volgende:
  1. Open de MDIVWCTL.DLL met OLE-COM Object Viewer (x64) en genereer een IDL file.
  2. Genereer een header file: midl MDIVWCTL.IDL /h MDIVWCTL.h
  3. Genereer een tbl file: midl MDIVWCTL.IDL /tlb MDIVWCTL.tlb
Vervolgens heb ik in mijn code dit:

C++:
1
2
#import "MDIVWCTL.DLL"
#include "MDIVWCTL.h"


Het lukt me nu echter niet om deze code te gebruiken.

C++:
1
2
Document md();
md.Create("filename");

Levert de volgende foutmelding: error C2228: left of '.Create' must have class/struct/union

Volgens mij komt dit doordat de functionaliteit in de interfaces lijkt te zitten en de classes deze niet implementeren??? Ik heb geen idee hoe ik dit kan oplossen, wel lijken typedefs als de volgende me vrij zinloos:

C++:
1
typedef class Document Document;


De complete header file is hier te vinden.

Acties:
  • 0 Henk 'm!

  • Rowwan
  • Registratie: November 2000
  • Laatst online: 21:29
code:
1
2
3
4
5
6
7
8
9
10
11
12
class Document
{
public:
    void Create() {}
};

int main(int argc, char* argv[])
{
    Document md();
    md.Create();
    return 0;
}


Dit levert exact dezelfde foutmelding op.... (Tip: Kijk eens naar regel 9 :) )

Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
"Document md();" is een functie die een Document object teruggeeft. Natuurlijk kun je geen .Create member op een functie aanroepen, dat moet op het return object. Dus "md().Create(); "

Of, als md geen functie had moeten zijn, maar een Document object, dan had je'm gewoon als "Document md;" moeten definieren.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
MSalters schreef op dinsdag 24 augustus 2010 @ 10:05:
"Document md();" is een functie die een Document object teruggeeft. Natuurlijk kun je geen .Create member op een functie aanroepen, dat moet op het return object. Dus "md().Create(); "

Of, als md geen functie had moeten zijn, maar een Document object, dan had je'm gewoon als "Document md;" moeten definieren.
Eigenlijk maakt het niet uit wat ik precies doe, want geen enkele manier werkt. De haakjes bij de constructor hadden idd daar niet moeten staan en de Create functie initialiseert het object (of iig in C#). Maar hoe dan ook compiled het niet, de klasse Document lijkt gewoon niets te kunnen, omdat het niets implementeerd??

Acties:
  • 0 Henk 'm!

  • Rowwan
  • Registratie: November 2000
  • Laatst online: 21:29
Die typedef die er staat is niet zinloos. Wat je nu eigenlijk gemaakt hebt is het volgende:
code:
1
2
3
4
5
6
int main(int argc, char* argv[])
{   
    class Document md();
    md.create();
    return 0;
}


Als ik naar de header kijk, zie ik dat de Create uit de (abstracte) interface IDocument komt. De definitie van Document staat niet in deze header.

Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
De definitie van Document staat niet in deze header.
Dat is dus precies mijn probleem en ik heb ook geen idee hoe ik aan deze definitie zou moeten komen.

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22:35
Memorice schreef op dinsdag 24 augustus 2010 @ 16:49:
Dat is dus precies mijn probleem en ik heb ook geen idee hoe ik aan deze definitie zou moeten komen.
Wat is de reden dat je die Create wilt aanroepen dan? Is dat de juiste manier om deze dll te gebruiken?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
farlane schreef op dinsdag 24 augustus 2010 @ 18:16:
[...]


Wat is de reden dat je die Create wilt aanroepen dan? Is dat de juiste manier om deze dll te gebruiken?
Volgens mij is dat idd de manier om deze dll te gebruiken, iig werkt het met dezelfde DLL zo in C#, zie ook de openings post.

Acties:
  • 0 Henk 'm!

  • Lone Gunman
  • Registratie: Juni 1999
  • Niet online
Volgens mij haal je twee dingen door elkaar, namelijk hoe je modi gebruikt in c# of c++/cli en hoe je 't gebruikt in native c++.

Het gequote stukje van microsoft dat aangeeft dat je c++ kan gebruiken gaat waarschijnlijk over c++/cli, en in dat geval krijg je code die veel lijkt op hoe je het in c# doet:

C++:
1
2
3
4
5
MODI::Document^ md = gcnew MODI::Document();
md->Create(filename);
md->OCR(MODI::MiLANGUAGES::miLANG_ENGLISH, true, true);
MODI::Image^ image = (MODI::Image^)md->Images[0];
return image->Layout->Text;


Maar in native c++ gaat het helaas niet op die manier en zul je het toch moeten zoeken in de richting van de eerste twee links die je in de ts gaf. Waarschijnlijk is de mfc afhankelijkheid nog wel te verwijderen, maar mooier zal het er niet op worden :+

Nog een heel ander punt: je wilt het component gebruiken met in-memory afbeeldingen ivm performance, maar weet je wel zeker dat de api van modi dit ondersteunt? Als ik een beetje browse mbv intellisense zie ik nergens een api om een in-memory afbeelding toe te voegen, alleen de create api die een filename verwacht. Misschien zie ik het over 't hoofd, maar het lijkt me wel handig om eerst te kijken of het uberhaupt mogelijk is... anders zit je sowieso op een dood spoor en kun je net zo goed je huidige oplossing gebruiken.

Mocht het wel blijken te kunnen, zou je eventueel nog kunnen overwegen om je huidige oplossing uit te breiden door shared memory te gebruiken tussen je main app en je c# console app. Ook niet echt een nette oplossing, maar dan heb je wel het gemak van modi icm c#.

Experience has taught me that interest begets expectation, and expectation begets disappointment, so the key to avoiding disappointment is to avoid interest.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:27

.oisyn

Moderator Devschuur®

Demotivational Speaker

Rowwan schreef op dinsdag 24 augustus 2010 @ 16:05:
Die typedef die er staat is niet zinloos.
De typedef is zinloos. De declaration van de class Document, de in de typedef wordt gedaan, echter niet.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
Nog een heel ander punt: je wilt het component gebruiken met in-memory afbeeldingen ivm performance, maar weet je wel zeker dat de api van modi dit ondersteunt? Als ik een beetje browse mbv intellisense zie ik nergens een api om een in-memory afbeelding toe te voegen, alleen de create api die een filename verwacht. Misschien zie ik het over 't hoofd, maar het lijkt me wel handig om eerst te kijken of het uberhaupt mogelijk is... anders zit je sowieso op een dood spoor en kun je net zo goed je huidige oplossing gebruiken.
Ik denk dat ik het voorlopig idd op de huidige oplossing hou.
Pagina: 1