DLL's für VB

Es gibt eine Vielzahl von Bereichen, für die Visual Basic nicht die geeignetsten Mittel zur Verfügung stellt. Dies betrifft z.B. zeitkritische Routinen in der Bildverarbeitung, oder hardwarenahe Berechnungen auf Bitebene, zu denen man am liebsten sogar Assembler heranziehen möchte.

Ergo kommt selbst ein eingefleischter Basicfan manchmal nicht Drumherum, zumindest einen verstohlenen Blick auf die VC-IDE zu werfen.

Aber selbst alte C-Hasen tun sich am Anfang schwer mit dem Schreiben einer DLL, die von außen (von VB natürlich) bequem zu handhaben ist.

B. Olaf Rasch 04/2003

 Anregungen oder Tipps an B. Olaf Rasch
 
  Einführung voriges Thema [ Top ] nächstes Thema

Für versierte VB-Programmierer ist es manchmal notwendig, bei geschwindigkeitskritischen Routinen auf den Einsatz von DLL's zurückzugreifen, die sie selbst unter Visual C++ entwickeln möchten. Dieser Artikel erläutert anhand eines einfachen Beispiels, mit welchen Mitteln die Namen von DLL-Funktionen nach außen gelegt werden können, um sie von VB aus über eine Declare-Anweisung aufzurufen. Die hier gezeigte Vorgehensweise ist im allgemeinen für die Herstellung von DLL's zu verwenden und kann somit als Vorlage für eigene Entwicklungen genutzt werden.

Der Code umfasst sowohl ein VB5-Projekt (UseDLL.prj) als auch ein VC-Projekt (usedll.dsw), welches mit VC++5.0 erstellt wurde. Da ich voraussetze, dass du bereits Erfahrungen im Umgang mit der VC-IDE hast, gehe ich im folgenden auch nur am Rande auf diesbezügliche Details ein und beschränke mich auf die Erläuterung der einzelnen Projektdateien.

 
  Aufbau voriges Thema [ Top ] nächstes Thema

Im vorliegenden Beispiel soll die Differenz zweier Integerzahlen ermittelt werden, die in einem Formular eingegeben worden sind. Hierzu brauchen wir eine Form, die zwei Textfelder zur Eingabe der Zahlen und einen Button bereitstellt, der dem Aufruf der DLL-Funktion (USEDLL_test) dient.

Die Liste der Controls im Standard-EXE-Projekt umfasst:

eine Form (Name: frmMain),
 

  ein Label (Name: labPara) zur Info,

 

  ein TextBox-Feld (Name: txtPara / Index: 0 und 1),

 

  einen Button (Name: btnDiff).

Die Dateien des VC-Projektes sind:

usedll.dsw (Projektdatei)

  usedll.h (Headerdatei)

  usedll.cpp (Code)

  usedll.def (Definedatei)

 
  VB Code voriges Thema [ Top ] nächstes Thema

Normalerweise wird die fertige DLL im Windows-Systemordner platziert, wo sie von der Declare-Anweisung in der Regel auch erwartet wird, so dass es reicht, hinter dem Schlüsselwort Lib lediglich den Namen der DLL-Datei anzugeben.

Während der Entwicklungszeit jedoch befindet sich die DLL noch in einem Ordner des VC-Projektes, so dass hier der komplette Name inklusive Pfad benötigt wird, damit die DLL gefunden werden kann.

Um eventuelle Codeänderungen zwischen Test- und Auslieferungsversion möglichst gering zu halten, bedienen wir uns des #If-#Then-#Else-Konstruktes, um diese beiden Fälle zu unterscheiden.

Über die (Bool-)Konstante SYSTEM_DLL legen wir fest, ob unsere DLL noch in der Entwicklungsumgebung verweilt oder bereits im System-Ordner zu suchen ist. Je nach Status von SYSTEM_DLL wird nun entweder der #If- oder der #Else-VB-Codeblock interpretiert/compiliert.

Option Explicit

#Const SYSTEM_DLL = False

#If SYSTEM_DLL Then
  Private Declare Function
USEDLL_test Lib "usedll.dll" _
    (ByVal t As String, ByVal a As Long, ByVal b As Long) As Long
#Else
  Private Declare Function
USEDLL_test _
    Lib "c:\bor\research\usedll\dll\Release\usedll.dll" _
    (ByVal t As String, ByVal a As Long, ByVal b As Long) As Long
#End If
 
Private Sub
btnDiff_Click()
  Dim d As Long
  d = USEDLL_test("Hallo Meister!", Val(txtPara(0)),Val(txtPara(1)))
  MsgBox "Die Differenz beträgt " & d, vbOKOnly, "Ergebnis"
End Sub

Bevor du den Code ausführst, musst du im #Else-Zweig den Pfadnamen von usedll.dll natürlich deiner eigenen Entwicklungsumgebung anpassen, sonst kann die DLL nicht gefunden werden.

Wenn die Funktion USEDLL_test aufgerufen wird, meldet sie sich mit einer MessageBox. Dabei zeigt sie den Text an, den wir ihr als ersten Parameter übergeben haben.

Nachdem wir das Ergebnis erhalten haben, lassen wir es uns zur Kontrolle in einer eigenen MessageBox anzeigen

 
  Die C++ Headerdatei voriges Thema [ Top ] nächstes Thema

Eine Headerdatei stellt sozusagen das Interface zwischen dem eigentlichen C-Code (der in der C/CPP-Datei steht) und der Außenwelt dar. Hier findet man globale Definitionen und Aufrufparameter der Public-Funktionen.

Für uns ist der Ausdruck __declspec( dllexport ) __stdcall von Interesse: er bewirkt, dass die jeweilige Funktion exportiert wird, d.h. von außen genutzt werden kann.

#ifndef _USEDLL_
#define _USEDLL_
 
#ifdef __cplusplus
extern "C" {  // C-Deklarationen für C++
#endif
 
#define EXP_LONG __declspec( dllexport ) long __stdcall

EXP_LONG USEDLL_test (char*t,long a,long b);
 
#ifdef  __cplusplus
}
#endif
 
#endif // _USEDLL_
 
  Der C++ Code voriges Thema [ Top ] nächstes Thema

In diesem Modul befindet sich der eigentliche Code. Hier interessiert uns neben der Funktion selbst (die lediglich eine MessageBox anzeigt und die Differenz von a und b zurückliefert) der Ausdruck #pragma comment(linker, "/DEF:usedll.def")

Damit wird der Compiler angewiesen, die Datei usedll.def zu berücksichtigen, die sich natürlich mit im Projekt befinden muss. In ihr wird nämlich explizit vermerkt, welche Funktionen von außen unter ihrem Originalnamen angesprochen werden können.

//
// USEDLL
//
// Beispiel zum Schreiben einer DLL
// mit korrekt exportierten Funktionsnamen
//

 
#define   STRICT     // wg. type checking
#include <windows.h> // wg. MessageBox
#include <stdlib.h>  // wg. abs()

#include "usedll.h"

// damit die Funktionsnamen leserlich exportiert werden
#pragma comment(linker, "/DEF:usedll.def")


//
// Testfunktion
//
// t = anzuzeigender Text
// a = dummy Longinteger
// b = dummy Longinteger
//
// returned: Differenz zwischen a und b
//

EXP_LONG USEDLL_test (char*t,long a,long b)
{
  MessageBox( NULL,  // handle of owner window
              t,             // address of text in message box
              "UseDLL Info", // address of title of message box
              MB_ICONINFORMATION | MB_OK);  // style of message box

  return(abs(a-b));  // result: difference
}
 
  Die C++ Definedatei voriges Thema [ Top ] nächstes Thema

Die Liste der nach außen gereichten Funktionsnamen fällt in unserem Fall bescheiden aus; es dreht sich nur im die Funktion USEDLL_test.

EXPORTS
   USEDLL_test

Falls keine def-Datei eingebunden wird, können die in der Header-Datei als exportiert deklarierten Funktionen selbstverständlich auch von außen angesprochen werden, jedoch sind die Namenskonventionen dann andere: Funktionsnamen erhalten einen führenden Unterstrich und bekommen ein @-Zeichen und eine Zahl angehängt, welche angibt, wie viele Bytes die Funktionsparameter benötigen.

So würde z.B. USEDLL_test nur als _USEDLL_test@12 exportiert werden und müsste von VB in einer Declare-Anweisung auch so definiert werden; notfalls mittels Alias:

Private Declare Function USEDLL_test Lib "usedll.dll" Alias _
  
      "_USEDLL_test@12" (ByVal t As String, ByVal a As Long, _
        ByVal b As Long) As Long

Da wir - als einfach strukturierte VB-Cracks - aber danach trachten, kryptische Bezeichnungen zu vermeiden (wir programmieren hier ja nicht in PERL *g*), sollte man sich die Verwendung von def-Dateien ruhig angewöhnen...

 
  Download des Projekts voriges Thema [ Top ]   

Im Anschluss können Sie sich hier das fertig Projekt herunterladen.

  Download
usedll.zip
 (16,3 kB)
Downloadzeit: <1 Min. - 28.8k / <1 Min. - ISDN Downloads bisher: [ 6809 ]

Startseite | VB/VBA-Tipps | Projekte | Tutorials | API-Referenz | Komponenten | Bücherecke | VB-/VBA-Forum | VB.Net-Forum | DirectX | DirectX-Forum | Foren-Archiv | VB.Net | Chat | Links | Suchen | Stichwortverzeichnis | Feedback | Impressum

Seite empfehlen Bug-Report
Letzte Aktualisierung: Donnerstag, 22. Mai 2003