aLeXanDer.. Geschrieben 16. Februar 2010 Geschrieben 16. Februar 2010 (bearbeitet) Hallo Community, C++ RadStudio 2009 Indy 10.1.1. Ich habe mir ein einfaches Testprogramm geschrieben mit einem Formular zum versenden von EMails. Dazu habe ich die Komponenten TIdSMTP und TIdMessage genutzt. Funktioniert einwandfrei. Nun möchte ich dieses aber in eine DLL integrieren. Ich habe ein DLL-Projekt erstellt. In dem Projekt befindet sich eine Unit1.cpp , sowie die Sendmail.cpp und Sendmail.h. In den Sendmaildateien habe ich exakt den selben Code wie in dem Beispielprojekt. //------------------------------------------------------------------------------ #include <vcl.h> #pragma hdrstop #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); //ZUGRIFFSVERLETZUNG!!! 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; } .... Sendmail.h #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; ...... In der Unit1.cpp den Aufruf, bzw. das Anlegen der Sendmail TSendmail* SM = new TSendmail(); Jedoch wenn ich mein Programm starte, mit dem ich auf die DLL zugreife, erhalte ich im Konstruktor, beim Anlegen der TIdMessage, bzw. TIdSMTP eine Zugriffsverletztung. Erste 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) Ich hab aber keine Ahnung mehr was ich noch machen kann, da es im testprogramm ohne Probleme funktioniert?! Bearbeitet 16. Februar 2010 von aLeXanDer.. Zitieren
VaNaTiC Geschrieben 16. Februar 2010 Geschrieben 16. Februar 2010 Hab ich das richtig verstanden, dass Du ein DLL-Projekt erstellt hast in welchem die Definition Deiner Klasse TSendmail implementiert ist? Und dann möchtest Du aus Deinem EXE-Projekt diese Klasse aus der DLL nutzen? Ist Deine DLL eine Borland Runtime Library (*.bpl)? Und ist das auch in Deinen EXE-Projekt-Optionen so eingestellt? "Normale" Dynamic Link Libraries (*.dll) exportieren Funktionen, keine Klassen. Zitieren
aLeXanDer.. Geschrieben 16. Februar 2010 Autor Geschrieben 16. Februar 2010 Nein sie ist eine .dll ich erhalte die Dateien .dll .lib und die übliche .tds und .map In dem Projekt selber habe ich nur das Laden der DLL ok = 0; sl = new TStringList(); hMod = LoadLibrary ("FrimatSendmail.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); //............... // .... 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); adrMerker = CSM(sl); if (adrMerker == NULL) return 0; ok = 2; return 1; } In dem Projekt der DLL habe ich als Hostanwendung dann dieses Projekt angegeben. Also führt er beim Compilieren der DLL, das Projekt1.exe aus, von der ich auf die DLL zugreife. Was müsste man in den EXE-Projekt-Optionen einstellen? und Wo? Auszug aus Unit1.cpp aus dem DLL-Projekt //------------------------------------------------------------------------------ extern "C" _declspec(dllexport) void* ConnectSM(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; } sl->Add("Connect OK"); return SM; } //------------------------------------------------------------------------------ Zitieren
VaNaTiC Geschrieben 16. Februar 2010 Geschrieben 16. Februar 2010 Das mit der Hostanwendung ist soweit ich weiss nur zum Debuggen/Testen/Starten aus der IDE. Deine ConnectSM() Funktion schaut problematisch aus. Du solltest keine VCL-Komponenten als Parameter/Rückgaben verwenden. D.h. keine TStringList, sondern lieber feste Parameter mit char* oder mit Stringlängenangabe. Innerhalb der "normalen" DLL kannst Du dann ohne Probleme VCL-Komponenten nutzen. Nur die Parameter/Rückgaben - also die exportierten Funktionen - sollten Standard-C sein. Zitieren
aLeXanDer.. Geschrieben 16. Februar 2010 Autor Geschrieben 16. Februar 2010 Also die DLL hat schon vorher existiert, ich wollte sie jetzt eigentlich nur auf den neuen Compiler umstellen, mit dem neuen Indy. Daran hab ich also nichts geändert. Die ConnectSM() war auch schon vorher so programmiert. Das Problem, liegt ja in der aller ersten Zeile der ConnectSM() -Funktion in TSendmail* SM = new TSendmail(); wo er dann TidSMTP oder TIdMessage mit new anlegen will. Da bekomm ich die Zugriffsverletzung Zitieren
aLeXanDer.. Geschrieben 17. Februar 2010 Autor Geschrieben 17. Februar 2010 Da es ein bestehndes Projekt war, standen in der Projektdatei noch Leichen alter Pfade... Hab das Projekt neu erstellt...Siehe da es funktioniert Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.