Zum Inhalt springen

Indykomponenten in einer DLL


aLeXanDer..

Empfohlene Beiträge

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 von aLeXanDer..
Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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;


}

//------------------------------------------------------------------------------


Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...