Indykomponenten in einer DLL
-
Hallo community,
Ich nutze Codegear RAD Studio 2009
Indy 10 (...120.bpl)Ich habe folgendes Problem, ich habe mir ein Testprogramm zum
Versenden von Emails mit den IndyKomponenten geschrieben. In dem Testprogramm habe ich einfach die Komponenten IdSMTP und IdMessage auf das Formular gezogen und genutzt.
Nun will ich das ganze aber in einer .DLL haben.
Ich habe den Code in ein neues DLL-Projekt kopiert und anschließend compiliert.
Wenn ich nun die DLL Aufrufe, erhalte ich immer eine Zugriffsverletzung!
Das ganze passiert wenn der Compiler, auf folgende CodeZeilen trifft._fastcall TSendmail::TSendmail() { Fehlertext = new TStringList(); //Klappt noch Message1 = new TIdMessage(Application);//ZUGRIFFSVERLETZUNG SMTP1 = new TIdSMTP(Application); SMTP1->OnStatus = SMTP1OnStatus; Fehler = false; Fehlertext->Clear(); }
Hier der Code der Unit1.cpp in der DLL
//------------------------------------------------------------------------------ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved) { return 1; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ extern "C" _declspec(dllexport) void* ConnectSM(TStringList* sl) //extern "C" _declspec(dllexport) void ConnectSM(void* ptr, TStringList* sl) { TSendmail* SM = new TSendmail(); SM->Connect(sl->Strings[0], sl->Strings[1], sl->Strings[2], sl->Strings[3]); // Host, Port, UserID (E-Mail-Account), Passwort if (SM->FehlerSendmail()) { sl->Add("Fehler beim Connect:"); for (int i=0; i < SM->Fehlertext->Count; i++) sl->Add(SM->Fehlertext->Strings[i]); SM->Fehlertext->Clear(); delete SM; return NULL; // ptr = NULL; // return; } sl->Add("Connect OK"); return SM; // ptr = SM; // return; } //------------------------------------------------------------------------------ extern "C" _declspec(dllexport) bool SendSM(void* adr, TStringList* sl) { TSendmail* SM = (TSendmail*)adr; SM->Send(sl->Strings[4], sl->Strings[5], sl->Strings[6], sl->Strings[7]); // ToAdr, Subject, Body, FromAdr if (SM->FehlerSendmail()) { sl->Add("Fehler beim Send:"); for (int i=0; i < SM->Fehlertext->Count; i++) sl->Add(SM->Fehlertext->Strings[i]); SM->Fehlertext->Clear(); SM->Disconnect(); delete SM; return false; } sl->Add("Send OK"); return true; } //------------------------------------------------------------------------------ extern "C" _declspec(dllexport) bool DisconnectSM(void* adr, TStringList* sl) { TSendmail* SM = (TSendmail*)adr; SM->Disconnect(); for (int i=0; i < SM->Fehlertext->Count; i++) sl->Add(SM->Fehlertext->Strings[i]); SM->Fehlertext->Clear(); delete SM; sl->Add("Disconnect OK"); return true; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Includes habe ich so wie aus meinem testprogramm eingefügt.
KOmm nicht mehr weiteR?!mfg
-
Hallo
In der DLL kannst du nicht das Application-Objekt aus dem Hauptprogramm benutzen.
Das ist kein Problem, verwende in den Konstruktoren von IdMessage und IdSMTP statt Application den Null-Zeiger. Natürlich must du dann selber die beiden Instanzen löschen, sobald du diese nicht mehr brauchst. So wie dein Code aussieht, sollte dafür der Destruktor von TSendmail zuständig sein.bis bald
akari
-
Erhalte trotz der Änderung auf NULL
folgende FehlermeldungErste Gelegenheit für Exception bei $7C81EB33. Exception-Klasse EAccessViolation mit Meldung 'Zugriffsverletzung bei Adresse 5077B88E in Modul 'indy120.bpl'. Lesen von Adresse 00000004'. Prozess Project1.exe (3048)
Das hier ist mein Programm mit dem ich die DLL aufrufe
ok = 0; sl = new TStringList(); hMod = LoadLibrary ("Sendmail.dll"); if (!hMod) { sl->Add("Fehler bei LoadLibrary (FrimatSendmail.dll)"); return; } void* farproc1 = GetProcAddress (hMod, "_ConnectSM"); // Tiefstrich ganz wichtig !!! if (!farproc1) { FehlerAnzeigen("ConnectSM"); FreeLibrary (hMod); return; } CSM = reinterpret_cast<ConnectSM>(farproc1); void* farproc2 = GetProcAddress (hMod, "_SendSM"); // Tiefstrich ganz wichtig !!! if (!farproc2) { FehlerAnzeigen("SendSM"); FreeLibrary (hMod); return; } SSM = reinterpret_cast<SendSM>(farproc2); void* farproc3 = GetProcAddress (hMod, "_DisconnectSM"); // Tiefstrich ganz wichtig !!! if (!farproc3) { FehlerAnzeigen("DisconnectSM"); FreeLibrary (hMod); return; } DSM = reinterpret_cast<DisconnectSM>(farproc3); ok = 1; } //------------------------------------------------------------------------------ _fastcall TSendmailF::~TSendmailF() { delete sl; if (hMod != NULL) FreeLibrary (hMod); } //------------------------------------------------------------------------------ // .... bool __fastcall TSendmailF::Connect(AnsiString host, AnsiString port, AnsiString userid, AnsiString pw) { if (ok < 1) { sl->Add("Connect-Aufruf nach Fehler im Konstruktor"); return 0; } sl->Clear(); sl->Add(host); sl->Add(port); sl->Add(userid); sl->Add(pw); // CSM(adrMerker, sl); //Hier erfolgt der Aufruf des Konstruktors der DLL und die Zugriffsverletzung adrMerker = CSM(sl); if (adrMerker == NULL) return 0; ok = 2; return 1; } //------------------------------------------------------------------------------
Liegts doch an den Includes?!
-
Meine Indyversion wird mit 10.1.1 angezeigt.
Zu alt?!
-
Also mit einer neueren IndyVersion erhalte ich dennoch diesen Fehler.
Zugriffsverletzung in indy120.bpl...
#include "TSendmail.h" //------------------------------------------------------------------------------ #pragma package(smart_init) #pragma link "IdMessage" #pragma link "IdExplicitTLSClientServerBase" #pragma link "IdMessageClient" #pragma link "IdSMTP" #pragma link "IdSMTPBase" #pragma link "IdTCPClient" #pragma link "IdTCPConnection" //------------------------------------------------------------------------------ _fastcall TSendmail::TSendmail() { Fehlertext = new TStringList(); Message1 = new TIdMessage(NULL); SMTP1 = new TIdSMTP(NULL); SMTP1->OnStatus = SMTP1OnStatus; Fehler = false; Fehlertext->Clear(); } //------------------------------------------------------------------------------ _fastcall TSendmail::~TSendmail() { if (SMTP1->Connected()) SMTP1->Disconnect(); delete SMTP1; delete Message1; delete Fehlertext; } //------------------------------------------------------------------------------
Header
//--------------------------------------------------------------------------- #ifndef TSendmailH #define TSendmailH //--------------------------------------------------------------------------- //#include <vcl.h> //#include <ScktComp.hpp> //#include "CSHeader.h" //#include <Psock.hpp> #include "IdMessage.hpp" #include "IdExplicitTLSClientServerBase.hpp" #include "IdMessageClient.hpp" #include "IdSMTP.hpp" #include "IdSMTPBase.hpp" #include "IdTCPClient.hpp" #include "IdTCPConnection.hpp" //------------------------------------------------------------------------------ class TSendmail { protected: private: bool Fehler; public: TStringList* Fehlertext; TIdSMTP *SMTP1; TIdMessage *Message1; //Si043 neu void __fastcall TSendmail::SMTP1OnStatus(TObject *ASender, const TIdStatus AStatus, const UnicodeString AStatusText); void __fastcall TSendmail::Connect(AnsiString host, AnsiString port, AnsiString userid, AnsiString pw); void __fastcall TSendmail::Send(AnsiString ToAddress, AnsiString Subject, AnsiString Body, AnsiString FromAddress); void __fastcall TSendmail::Disconnect(); bool __fastcall TSendmail::FehlerSendmail(); _fastcall TSendmail::TSendmail(); _fastcall TSendmail::~TSendmail(); }; //------------------------------------------------------------------------------ #endif
Ich verzweifel grad
Ihn schmeißts immer im Konstruktor der DLL.
Bei dem new TIdMessage(NULL);
mit Debuggen siehts so aus als ob der 2 mal auf diese Zeile kommt.Die DLL hat vorher schon existiert und unter früheren RadStudio Versionen ohne Probleme funktioniert.
Mit dem neuen Indy und der Umstellung auf Unicode kamen geringfügige Änderungen hinzu, aber keine die den Konstruktor geändert hat.Hat jemand eine Erklärung oder Hilfestellung für mich?!
-
aLeXanDer.. schrieb:
Hat jemand eine Erklärung oder Hilfestellung für mich?!
Debugger benutzen. Gegebenenfalls einen Debug-Build der Indy-Bibliotheken erstellen.
Das Problem wird vermutlich darauf zurückzuführen sein, daß du Delphi-Klassen zwischen Anwendung und DLL austauschst. Das ist nur dann möglich, wenn du mit Laufzeit-Packages linkst.