Einbinden in Delphi (API-Schnittstelle)
Benötigte Dateien:
Zum Einbinden der DLL in Delphi-Programme benötigen Sie folgende Dateien:
- TcAdsDll.dll - dynamische Funktionsbibliothek
Die TcAdsDll.dll befindet sich im ‚System32'-Verzeichnis von Windows NT/2000.
Optional für statisches Linken:
HINWEIS: Die Deklarationsdateien TcAdsAPI.pas und TcAdsDEF.pas sind im Archiv delphi_adsdll_api_units.zip enthalten.
- Portierte TcAdsAPI.h C++ Headerdatei mit den Deklarationen der Ads-Funktionen: TcAdsAPI.pas
- Portierte TcAdsDEF.h C++ Headerdatei mit den Deklarationen der Strukturen und Konstanten: TcAdsDEF.pas
Um die Bespiele selbst übersetzen zu können benötigen Sie:
- Delphi 5.0 oder höher;
- ADS Summenkommando-Beispiele: Delphi 6.0 + Update Pack 2 oder höher;
- ADS Multithreading-Beispiel: Delphi 7.0 + Update 7.1 oder höher;
Theoretisch können Sie die Beispiele auch mit einer neueren Delphi-Version bearbeiten. Oft sind nach der Konvertierung des Projekts zusätzliche Anpassungen im Sourcecode an die neue Delphi Version vorzunehmen. Diese Anpassungen können z. B. durch eine Änderung im Compiler bei der Behandlung der VARIANT-Datentypen oder Stringdatentypen notwendig sein.
DLLs in Delphi aufrufen
Bevor Sie Routinen aufrufen können, die in der TcAdsDLL definiert sind, müssen Sie diese Routinen importieren. Der Import kann auf zwei Arten durchgeführt werden: Sie deklarieren eine Prozedur oder Funktion als external, oder Sie rufen die Windows-API direkt auf. Bei beiden Methoden werden die Routinen erst zur Laufzeit zur Anwendung gelinkt. Das bedeutet, dass die DLL zur Compilierzeit nicht benötigt wird. Es bedeutet aber auch, dass der Compiler nicht überprüfen kann, ob eine Routine korrekt importiert wird.
Statisches laden der DLL-Funktionen
Die einfachste Art, eine Prozedur oder Funktion zu importieren, besteht darin, sie mit der Direktive external zu deklarieren:
procedure MyDllFunction; external
'MYLIB.DLL';
Durch diese Deklaration wird beim Programmstart die Datei MYLIB.DLLgeladen. Während der Ausführung des Programms bezieht sich der Bezeichner MyDllFunction immer auf denselben Eintrittspunkt in derselben DLL.
Sie können die Deklaration einer importierten Routine direkt in das Programm oder die Unit einfügen, in dem bzw. der sie aufgerufen wird. Um Ihre Programme leichter pflegen zu können, sollten Sie aber alle external-Deklarationen in einer separaten „Import-Unit“ zusammenfassen. Diese Unit enthält dann auch die Konstanten und Typen, die für die Schnittstelle zur DLL erforderlich sind (die Unit Windows von Delphi ist dafür ein gutes Beispiel). Andere Module, die auf die Import-Unit zugreifen, können alle darin deklarierten Routinen aufrufen.
Ausführliche Informationen über external-Deklarationen und dynamisches Laden über Aufrufe der Windows-API finden Sie in der Delphi Online-Hilfe.
Folgende Regeln sind bei einer Portierung der TcAdsDLL in Pascal-Applikationen einzuhalten:
- Alle C++ Makros müssen in entsprechenden Pascal-Funktionen umgewandelt werden;
- Alle C++ Datentypen müssen in Pascal-Typen umgewandelt werden;
- Die Datentypen der C++ Funktionsparameter müssen in entsprechenden Pascal-Datentypen umgewandelt werden;
Die wichtigsten Deklarationen der TcAdsDLL.DLL wurden in zwei Units zusammengefasst: TcAdsDEF.pas und TcAdsAPI.pas. Wenn Sie die Funktionen statisch laden wollen, müssen diese Units über eine Uses-Klausel in die Delphi-Applikation eingebunden werden.
Infos über Delphis memory manager in Multithreading-Applikationen
Der "memory manager" von Delphi benutzt "critical sections" um Threadsicherheit in Multithreading-Applikationen gewährleisten zu können. Die "critical sections" werden aber nur dann verwendet, wenn eine nicht so bekannte Systemvariable IsMultiThread auf True gesetzt wurde. Die IsMultiThread Variable ist in dem unit ‘System.pas’ definiert, welches implizit von allen Delphi units verwendet wird.
Immer dann, wenn die Applikation oder eine eingebundene Bibliothek mehrere Threads verwendet, müsste die Variable IsMultithread auf True gesetzt werden. Andernfalls ist die Applikation oder die Bibliothek nicht "thread safe".
IsMultiThread wird aber nur dann implizit gesetzt, wenn der Entwickler in der Applikation oder der Bibliothek das Delphi TThread Objekt benutzt.
Der memory manager von Delphi geht z. B. davon aus, dass es sich um eine Singlethread-Applikation handelt, wenn:
- Eine DLL eingebunden wird die mehrere Threads verwendet;
- Kein TThread Objekt vom Entwickler benutzt wird;
Die Zugriffe auf gemeinsame Resourcen werden in diesem Fall nicht verriegelt.
Die TcAdsDLL.dll verwendet, aber eigene Threads. Aus diesem Grund muss sichergestellt werden, dass die IsMultiThread Variable auf True gesetzt ist sobald die TcAdsDLL in eine Delphi-Applikation eingebunden wird.
In den aktuellen Versionen der Units: TcAdsDEF.pas und TcAdsAPI.pas wird die IsMultiThread Variable in der initialization section auf True gesetzt. Der Entwickler ist aber selbst dafür verantwortlich sicherzustellen, dass die Variable in einer Multithreading-Applikation zum richtigen Zeitpunkt auf jeden Fall gesetzt ist.