(c++) ist HANDLE ein "normaler" Datentyp?

SchindlerD

Grünschnabel
Hallo Leute,

ich habe ein Problem beim Einbinden einer *.dll bzw. einer *.lib. Vielleicht gibts da ja ein Tutorial drüber? Für Hinweise wäre ich dankbar, gefunden habe ich nichts...
Ich benutze übrigens VisualStudio 2005 und habe versucht, das ganze in einer Win32 Consolenanwendung hinzukriegen (nachdem ich bei der managed-Variante mit GUI wiedermal kläglich gescheitert bin)
Jedenfalls kommt es mir fast vor, als würde der Datentyp HANDLE, der in einer zur *.dll gelieferten *.h Datei verwendet wird, nicht erkannt. Muss ich für die Verwendung davon irgendwelche zusätzlichen header einbinden? In msdn gibts den Datentyp (falls es einer sein sollte) ziemlich oft, deswegen dachte ich, das wird so schon passen...
Prinzipiell habe ich aber keine Ahnung was falsch läuft, bin also über jeden Hinweis glücklich.

Bis bald
SchindlerD
 
Hallo,

der Datentyp HANDLE ist als "typdef LPVOID HANDLE" deklariert und du musst dazu den Header "windows.h" verwenden.

Zum Einbinden einer (regulären) DLL gibt es zwei Wege:
1. Statisch, indem man die mitgelieferte Import-Library zum Programm dazulinkt.
2. Dynamisch, indem man die DLL mit LoadLibrary() lädt und mit GetProcAddress() die exportieren Funktionen holt.

Gruß
MCoder
 
Morgen!

Also, windows.h ist in der headerdatei schon eingebunden, daran wirds wohl nicht liegen...
Hier mal ein wenig Code plus Fehlermeldung (insgesamt krieg ich über hundert Fehler zusammen, deshalb nur ein Auszug)
C++:
//...
#if defined (WIN32) && !defined (WIN9x)
#   if defined (XPASCAL)
#	define FEXTHANDLE  extern HANDLE pascal
#	define FEXTINT     extern int pascal
#	define FHANDLE     HANDLE pascal
#	define FINT        int pascal
#   else
#	define FEXTHANDLE  extern HANDLE
#	define FEXTINT     extern int
#	define FHANDLE     HANDLE
#	define FINT        int
#   endif
#endif
//...
#if defined (IPC01) && defined (WIN95)
FEXTHANDLE _open_xpc(unsigned long base16,
		     unsigned long base32,
		     long ipmemsize,
		     int ivec,
		     int ilevel);
#elif defined (HPVISA) && defined (WIN32)
FEXTHANDLE _open_xpc(HANDLE ohdl,
		     unsigned short vxibus,
		     unsigned short vxiaddr);
#else
FEXTHANDLE _open_xpc(short lbn);                           // hier die Fehler
#endif
Fehlermeldung:
syntax error : missing ';' before identifier '_open_xpc'
missing type specifier - int assumed. Note: C++ does not support default-int
Der letzte Fehler taucht gleich zweimal für die selbe Zeile auf.
Danach gibts nur noch Fehler wegen anscheinend fehlender Klammern.

Hättest du vielleicht ein Beispiel wie die Einbindung funktioniert? Danke schonmal!
 
Bist du sicher, dass du kein Managed C++ verwendest? Die Fehlermeldungen treten nämlich nur dort auf.

Gruß
MCoder
 
Im moment schreibe ich an nem "normalen" C++ Konsolenprogramm, weil ich das mit managed C++ (WindowsForm) nicht hingekriegt habe... Wollte erstmal probieren ob ich die "einfache" Variante zum Laufen kriege - Sorry, habe mich vielleicht falsch ausgedrückt...
Wo könnte ich denn nachschauen ob ich managed Code schreibe? Habe jedenfalls den Garbage Collector nicht angerührt...
 
Hallo, Konsolenprogramm ist schon ok. An welcher Stelle genau hast du denn die "windows.h" eingebunden? Schreibe sie doch mit in die "stdafx.h", dann wird sie auf jeden Fall rechtzeitig eingebunden.
 
Super, keine Fehlermeldung mehr! Danke!
Gibts eigentlich eine Möglichkeit herauszufinden, in welcher .dll die Funktionen der .h stehen? Ich hab da eine ganze Menge verschiedener mitgeliefert gekriegt und weiß jetzt nicht recht, welche überhaupt nötig sind...
 
Du kannst dir die einzelnen DLLs mit dem Tool "Depends" anschauen (liegt bei mir unter "...\Microsoft Visual Studio 8\Common7\Tools\Bin\"). Da werden die exportierten Funktionen angezeigt.

Gruß
MCoder
 
Super, die Version auf der Konsole funktioniert jetzt. Musste auch nur 2 der mitgelieferten *.dlls dazuhängen.
Jetzt versuche ichs mal mit der managed version.
C++:
    using namespace System::Runtime::InteropServices;

	[DllImport("CAS95.DLL")] extern "C" HANDLE _open_xpc(short lbn);
	[DllImport("CAS95.DLL")] extern "C" int _close_xpc(HANDLE hmpc);
	[DllImport("CAS95.DLL")] extern "C"	int _config_rec(HANDLE hmpc, char rx_pair, unsigned short speed);
Danach rufe ich die Funktionen im Programm ganz normal auf.
Wenn ich die release Version debugge kriege ich folgenden Fehler:
Die DLL CAS95.DLL: Das angegebene Modul wurde nicht gefunden. (Ausnahme von HRESULT: 0x8007007E) kann nicht geladen werden.
Aber auf dem "Zielrechner" läuft es!
Vermutlich liegt es an einer *.dll des Treibers? Wenn ich nämlich eine zusätzliche (sie heißt "VARINCD.DLL") in den release-Ordner schiebe, funktioniert das Programm zwar ohne Problem die *.dll zu finden, aber ich kriege folgende Fehlermeldung:
Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
VARINCD.DLL ist zwar schreibgeschützt, aber wenn ich den Haken bei den Eigenschaften raus mache kommt der Fehler trotzdem. Ich fände es auch nicht soo toll falls das Programm versuchen würde, in die *.dll reinzuschreiben...
Beim Öffnen der CAS95.dll mit dem Dependency Walker sind übrigens beide *.dlls, die ich zusätzlich dazugespeichert habe, angegeben. Wieso meckert das Programm dann nicht bei der Konsolen-Version?
Wie gesagt: auf dem Rechner an dem die Hardware installiert ist, die ich mit der *.dll ansprechen will, funktioniert das Programm ohne Fehlermeldung, ich habe nur die Befürchtung, der Fehler könnte dort auch früher oder später auftauchen!? Außerdem ließ sich die Konsolen-Version auch ohne Speicherfehler auf dem Entwicklungsrechner debuggen (ohne die VARINCD.dll) obwohl ich die selben Befehle verwendet habe.
Wo liegt denn mein Fehler?

Ich glaube, ich mag *.dlls nicht ;)
 
Wenn ich die release Version debugge
Respekt, sowas gelingt mir nur mit der Debug-Version :)


Du brauchst alle DLLs, die der Dependency Walker bei den Abhängigkeiten erkannt hat. Falls welche fehlen, kann die DLL nicht geladen werden und es kommt die etwas irreführende "nicht gefunden" - Meldung. Warum's in der Konsolen Version auch ohne geht, kann ich dir allerdings nicht erklären. Die Verwendung einer Import-Lib ist halt nicht ganz dasselbe, wie das dynamische Einbinden, was die Managed C++ Variante macht.

Die Meldung mit dem Schreiben in geschützten Speicher ist nicht sehr erhellend. Vermutlich ist die DLL abgeschmiert und hat damit diese Meldung verursacht. Auf dem Zielrechner ist vielleicht noch eine DLL oder eine sonstige Datei vorhanden (evt. im Systemverzeichnis?), die auf dem Entwicklungsrechner fehlt, aber gebraucht wird?
Auf jeden Fall solltest du diese externen Funktionsaufruf grundsätzlich in einen try-catch-Block packen, um evt. Fehler sauber abfangen zu können.

Gruß
MCoder
 
Zurück