Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Indykomponenten in einer DLL

Empfohlene Antworten

Veröffentlicht

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..

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.

  • Autor

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;


}

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


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.

  • Autor

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

Archiv

Dieses Thema wurde archiviert und kann nicht mehr beantwortet werden.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.