Wo ist die Referenz hin ??
-
Hallo Leute..
habe eine Klassengesteuerte C++ DLL zur Verfügung die ich gern in Delphi nutzen wollte. Die Lösung dafür war eine C- Wrapper- DLL in welcher ich eine Instanz der Klasse erzeuge und darauffolgend mittels exportierter Funktionen auf Funktionen dieser Klasse zugreife.
Hier der C++- Code:
#include "stdafx.h" #include "CTIMultiClt.h" #include "MultiCltMap.h" HWND targetWindow; BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } extern "C" __declspec(dllexport) bool ConnectToCAEServer(char* IP); extern "C" __declspec(dllexport) bool setApplClassName(char* ApplClassName); extern "C" __declspec(dllexport) int OpenLine(); extern "C" __declspec(dllexport) bool Disconnect(); class CSampleMultiClient : public CtMultiDevClient { public: CSampleMultiClient(void) {} virtual ~CSampleMultiClient(void) {} protected: // Überschreiben der Callback-Funktionen long OnEvent(const CtMultiDevMsg* a_pMultiDevMsg); long OnInfoEvent(const CtMultiDevMsg* a_pMultiDevMsg); long OnReply(const CtMultiDevReply* a_pMultiDevReply); }; long CSampleMultiClient::OnEvent(const CtMultiDevMsg* a_pMultiDevMsg) { [...] // Ist hier nicht erwähnenswert ! } long CSampleMultiClient::OnInfoEvent(const CtMultiDevMsg* a_pMultiDevMsg) { [...] // Ist hier nicht erwähnenswert ! } long CSampleMultiClient::OnReply(const CtMultiDevReply* a_pMultiDevReply) { [...] // Ist hier nicht erwähnenswert ! } //===================================================================================================================================== // wrapper functions CSampleMultiClient cti; // globale Referenz zur neu erzeugten Instanz // connect to CAEServer bool ConnectToCAEServer(char* IP) { if (S_OK != cti.OpenConnection(IP)) { return false; } else return true; } // Open Line int OpenLine() { HRESULT LO; long ReplyID; LO = cti.LineOpen("1169", ReplyID); if (S_OK == LO) { // Line geöffnet return 1; } if (E_NOINTERFACE == LO) { // Es besteht keine CTI Server Verbindung return 2; } }In Delphi rufe ich zuerst die "ConnectToCAEServer" - Funktion auf und übergebe dabei die IP- Adresse des Servers. Darauffolgend bekomme ich ein "true" zurück, somit besteht eine Verbindung. Danach öffne ich über die "OpenLine()"- Funktion die Line mit der Telefonnummer "1169"... dabei bekomme ich in Delphi folgende Meldung:
"Zugriffsverletzung bei 0x00b6fedc: Lesen von Adresse 0x00000005"
Wenn ich die "ConnectToCAEServer" - Funktion nicht aufrufe sondern sofort die "OpenLine()"- Funktion, dann bekomm ich ordnungsgemäß den Rückgabewert 2 -> "Es besteht keine CTI Server Verbindung".
Wenn ich die "OpenLine()"- Funktion folgendermaßen abändere:
// Open Line int OpenLine() { HRESULT LO; long ReplyID; CSampleMultiClient cti; // =============== lokal referenziert ===================================== cti.OpenConnection(IP) // =============== mit lokaler Instanz zum Server verbunden =============== LO = cti.LineOpen("1169", ReplyID); if (S_OK == LO) { // Line geöffnet return 1; } if (E_NOINTERFACE == LO) { // Es besteht keine CTI Server Verbindung return 2; } }...... bekomme ich den Rückgabewert 1 -> Line auf Server geöffnet .....
warum funktioniert die Geschichte nicht wenn ich die Klasse einmal global referenziere und dann über die exportierten Funktionen einzeln auf diese Instanz zugreife? Geht die Referenz verloren?
-
Keiner ne Idee ?
-
Ist zwar das C++-Forum - aber wie machst du das auf Delphi-Seite? Hast du die DLL über external-Deklarationen eingebunden? Oder über LoadModule/GetProcAddress-Aufrufe? Falls letzteres, du entlädst die DLL zwischen den Aufrufen doch nicht wieder, oder?
-
hallo 7H3 N4C3R .. in Delphi habe ich schon beide Varianten versucht. Beim dynamischen Laden der DLL wird das Handle dieser DLL erst beim Beenden des Programmes wieder frei gegeben ! Daran kanns also net liegen

-
Ich bin mir auch nicht sicher, ob du das so machen kannst mit dem globalen Objekt. IIRC ist das "eigentliche" Programm schon direkt nachdem der DLLEntryPoint gerufen wurde, wieder zu Ende, d.h. dein globales Objekt wird wieder abgeräumt. Mach doch mal ein Singleton draus (eins was sich 'nen Ponter merkt, kein Myers-Singleton) oder Debugausgaben rein in Konstruktor und Destruktor (meinetwegen in ein File oder so).
-
danke für deine antwort .. habe das problem aber mittlerweile schon gelöst !
in den überschriebenen callback- funktionen ( deren inhalt ich mit "[...]" gekennzeichnet habe ) waren noch printf's zur konsolenausgabe vorhanden .. diese haben diesen fehler erzeugt :).
ansonsten funktioniert alles soweit. das globale objekt/instanz bleibt so lange erhalten bis ich das handle der dll wieder freigebe.
gruß