AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Delphi-DLL in C++ benutzen

Ein Thema von MaxDelphi · begonnen am 7. Jul 2011 · letzter Beitrag vom 7. Jul 2011
Antwort Antwort
MaxDelphi

Registriert seit: 29. Jun 2009
17 Beiträge
 
#1

Delphi-DLL in C++ benutzen

  Alt 7. Jul 2011, 09:59
Hallo Forum,

ich muss eine DLL an einen Kunden geben der mit LabWindows/CVI von NI (AnsiC) arbeitet. Da ich Delphi-Programmierer bin erstelle ich die DLL in Delphi. Zum Testen nutze ich den C++Builder da ich nunmal RAD Studio XE besitze. Mein Laptop läuft mit Win7Pro(x64).

1. Ich habe die DLL mit einer Delphi-Applikation getestet (Dll-Funktionen statisch eingebunden) -> funktioniert.
2. Versuche die DLL statisch in C++ einzubinden hab ich überhaupt nicht hingekriegt.
3. Versuche die DLL zur Laufzeit in C++ einzubinden funktionieren bis zum laden der DLL. Funktionen aus der DLL gehen gar nicht.
4. Damit ich weiterkomme habe ich nochmal eine neue Minimal-DLL mit nur zwei Funktionen erstellt. Parallel dazu habe ich eine Minimalanwendung im C++Builder erstellt. Beides hänge ich hier an.

Mich interessiert im ersten Punkt:
- Wie krieg ich meinen Code zum Laufen?

Fernerhin eine Art Tutorial wie Delphi-DLL's erstellt werden müssen damit sie in C eingebunden werden können.
- Wie muss die DLL aussehen?
- Wie kann ich die LIB- und Header-Datei erzeugen (spezielle Projektoptionen in Delphi??) zur Weitergabe an den Kunden?
- Wie läßt sich die DLL dann in C++-Builder einbinden (statisch und zur Laufzeit)? In Delphi war das alles ganz verständlich, aber hier...

Ich vermute das hier auch der Aspekt Win7(x64) einen Einfluss hat.


Der Code:
Die DLL (in Delphi XE):
Delphi-Quellcode:
library Project1;

uses
  SysUtils,
  Classes;

{$R *.res}

function Min(X, Y: Integer): Integer; stdcall;
begin
  if X < Y then Min := X else Min := Y;
end;

function Max(X, Y: Integer): Integer; stdcall;
begin
  if X > Y then Max := X else Max := Y;
end;

exports
  Min,
  Max;

begin
end.
Der Code im C++ Builder:
Header:
Code:
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <FileCtrl.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:   // Von der IDE verwaltete Komponenten
   TButton *Button1;
   TLabel *Label1;
   TButton *Button2;
   TButton *Button3;
   TEdit *Edit1;
   TEdit *Edit2;
   void __fastcall Button1Click(TObject *Sender);
   void __fastcall Button3Click(TObject *Sender);
   void __fastcall Button2Click(TObject *Sender);
private:   // Anwender-Deklarationen
   HINSTANCE DllInstance;
public:      // Anwender-Deklarationen
   __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Implementierung:
Code:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "windows.h"
#include "winbase.h"
#include "Unit1.h"

#define LOAD_LIBRARY_AS_DATAFILE 0x00000002

//TCHAR dllToLoad[] = L"CEH_IPC.dll"; // The dll's complete name
//TCHAR dllToLoad[] = L"zlib.dll"; // The dll's complete name
TCHAR dllToLoad[] = L"Project1.dll"; // The dll's complete name
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
//   DllInstance = LoadLibrary((wchar_t *)"D:\CPP\Sandkasten\Test\CEH_IPC.dll");
   DWORD TestRes   = 12;
   if (!DllInstance) DllInstance = LoadLibraryEx(dllToLoad,NULL,LOAD_LIBRARY_AS_DATAFILE);
   if (DllInstance) Form1->Caption   = "DLL wurde geladen.";
   TestRes   = GetLastError();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
   if (DllInstance)
      if (FreeLibrary(DllInstance)) DllInstance = NULL;
   if (!DllInstance) Form1->Caption   = "DLL nicht geladen.";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
   typedef int (__stdcall *IMPFUNC) (int, int);
   IMPFUNC DLLFunktion = NULL;
   DWORD TestRes   = 12;
   if (DllInstance) {
//      DLLFunktion = (IMPFUNC)GetProcAddress(DllInstance, "_gzclose@16");
      DLLFunktion = (IMPFUNC)GetProcAddress(DllInstance, "Min");
      if (DLLFunktion) {
         TestRes = DLLFunktion(300,400);
         ShowMessage("Geht doch");
      }
      else {
         ShowMessage("Geht net");
      }
      TestRes   = GetLastError();
   }
}
//---------------------------------------------------------------------------
Schon das Laden der DLL mit LoadLibrary hat nicht geklappt, erst LoadLibraryEx brachte den nötigen Erfolg.
GetProcAddress findet die Funktion nicht und GetLastError liefert 126 zurück.


Bitte um Hilfe und Danke im voraus.
MfG,
MaxDelphi
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#2

AW: Delphi-DLL in C++ benutzen

  Alt 7. Jul 2011, 10:10
Code:
DllInstance = LoadLibraryEx(dllToLoad,NULL,LOAD_LIBRARY_AS_DATAFILE);
Du lädst die DLL ja auch als Datendatei. Ich bin mir nicht sicher, ob man dann Funktionen aus der DLL nutzen kann. Das MSDN geht im Moment leider nicht.

Und sind deine C++ Anwendungen auch 32-Bit Anwendungen?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
blauweiss

Registriert seit: 19. Jun 2007
142 Beiträge
 
#3

AW: Delphi-DLL in C++ benutzen

  Alt 7. Jul 2011, 10:28
Hallo MaxDelphi,

auf die Schnelle: ich würde als Aufrufkonvention cdecl anstelle von stdcall verwenden (in der Delphi-DLL).

Gruß
blauweiss
  Mit Zitat antworten Zitat
MaxDelphi

Registriert seit: 29. Jun 2009
17 Beiträge
 
#4

AW: Delphi-DLL in C++ benutzen

  Alt 7. Jul 2011, 10:59
Erstmal Danke für die schnelle Antwort.

@Lucki:
Der Hinweis ist korrekt, als Datendatei lassen sich keine Proceduradressen ermitteln. Aber was sollte man dafür benutzten (ich hab testweise LOAD_IGNORE_CODE_AUTHZ_LEVEL verwendet, damit ging es).

(((Wenn ich LoadLibrary benutzen könnte hätte ich das Problem gar nicht!)))
Ich werd verrückt jetzt geht auch LoadLibrary! Ich hab gestern den ganzen Tag gesucht und ursprünglich mit
Code:
DllInstance = LoadLibrary((wchar_t *)"D:\CPP\Sandkasten\Test\CEH_IPC.dll");
gearbeitet, nach einiger Recherche im Internet dann mit
Code:
DllInstance = LoadLibraryEx(dllToLoad,NULL,LOAD_LIBRARY_AS_DATAFILE);
gearbeitet und nicht mehr getestet ob auch
Code:
DllInstance = LoadLibrary(dllToLoad);
geht. Der ursprüngliche Fehler lag also in der Typumwandlung.

Also das erste Problem scheint gelöst zu sein.

@blauweis:
Deinen Hinweis werd ich nicht weiterverfolgen (siehe oben).

Bleibt die Fragestellung:
- Wenn ich eine DLL weitergeben will und der andere eine LIB- und eine Header-Datei braucht. Wie kann ich die erzeugen und auf die Schnelle mal in C++Builder testen?
MfG,
MaxDelphi
  Mit Zitat antworten Zitat
Robotiker
(Gast)

n/a Beiträge
 
#5

AW: Delphi-DLL in C++ benutzen

  Alt 7. Jul 2011, 11:21
- Wenn ich eine DLL weitergeben will und der andere eine LIB- und eine Header-Datei braucht. Wie kann ich die erzeugen und auf die Schnelle mal in C++Builder testen?
LIB-Dateien für den C++ Builder laufen nicht unbedingt mit anderen Compilern. Beim C++ Builder ist mit Coff2Omf ein Tool, das aus dem Visual C++ Format konvertieren kann. Aber meines Wissens nach nicht in die andere Richtung.
  Mit Zitat antworten Zitat
MaxDelphi

Registriert seit: 29. Jun 2009
17 Beiträge
 
#6

AW: Delphi-DLL in C++ benutzen

  Alt 7. Jul 2011, 12:21
@Robotiker:
Ich war scheinbar nicht exakt genug! Ich meinte: Eine DLL mit Delphi erstellen und (am besten nebenbei über Projektoptionen??? oder änlilches) beim Kompilieren/Linken die LIB- und Header-Datei erzeugen. Oder wenn das nicht geht ein Tool das diese Aufgabe übernimmt und eine entsprechende Beschreibung.

Für die Header-Datei könnte ich mir ein Übersetzungs-Tool vorstellen ähnlich headconv von Dr. Bob nur von Pascal nach C.

Ich habe bereits implib und impdef ausprobiert. implib bricht mit einer Fehlermeldung ab, erzeugt aber eine Lib-Datei. Hier fehlt mir wieder die Möglichkeit zu testen ob sie funktioniert. Kann sein das implib die Lib-Datei korrekt erzeugt hat und erst danach abbricht aber genau weiß ich das nicht.

Fehlermeldung von implib:
Implib funktioniert nicht mehr
Windows kann online nach ....
Details:
Problemsignatur:
Problemereignisname: APPCRASH
Anwendungsname: implib.exe
Anwendungsversion: 3.2.0.0
Anwendungszeitstempel: 00000000
Fehlermodulname: implib.exe
Fehlermodulversion: 3.2.0.0
Fehlermodulzeitstempel: 00000000
Ausnahmecode: c0000005
Ausnahmeoffset: 00013887
Betriebsystemversion: 6.1.7601.2.1.0.256.48
Gebietsschema-ID: 1031
Zusatzinformation 1: d893
Zusatzinformation 2: d8933a9100d220db76612cd68cf270ed
Zusatzinformation 3: 712b
Zusatzinformation 4: 712bad326e73717ee07100af4c008660

Lesen Sie unsere Datenschutzbestimmungen online:
http://go.microsoft.com/fwlink/?link...8&clcid=0x0407

Wenn die Onlinedatenschutzbestimmungen nicht verfügbar sind, lesen Sie unsere Datenschutzbestimmungen offline:
C:\windows\system32\de-DE\erofflps.txt


Bitte beachtet ich benutze Win7Pro(x64).
MfG,
MaxDelphi
  Mit Zitat antworten Zitat
Robotiker
(Gast)

n/a Beiträge
 
#7

AW: Delphi-DLL in C++ benutzen

  Alt 7. Jul 2011, 12:37
implib bricht mit einer Fehlermeldung ab, erzeugt aber eine Lib-Datei.
Eine Lib-Datei im Format des C++ Builders, die andere Compiler nicht lesen können.

Eine DLL mit Delphi erstellen und (am besten nebenbei über Projektoptionen??? oder änlilches) beim Kompilieren/Linken die LIB- und Header-Datei erzeugen.
Ich kenne den Compiler von LabWindows/CVI nicht, falls der kompatibel zu VC ist, könntest Du in der Tat beim Erzeugen des Delphi Projektes den Lib.exe von Visual C++ als Post-Build-Step aufrufen. Ob Lib.exe allerdings Delphi-DLLs verdaut, kann ich nicht sagen.

Das einzige Tool, das ich kenne, das Headerdateien aus *.pas Dateien erzeugt, ist der C++ Builder. Wenn man einem C++ Projekt eine Delphi Unit hinzufügt, baut er sich beim Übersetzen eine *.hpp Datei dafür. Die ist aber dafür gedacht die Unit aus einer Builder Anwendung zu nutzen, nicht um Dll-Exporte zu erzeugen.

Schreibt Dir doch selber ein Tool, das aus den Signaturen der Delphi-Funktionen die entsprechenden C-Header Einträge generiert und Code mit GetProcAddress-Aufrufen erzeugt. Dann kannst du auf die Lib-Dateien verzichten.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz