Discussion:
C++-DLL in Delphi nutzen
(zu alt für eine Antwort)
Siegfried Jess
2006-01-18 06:58:54 UTC
Permalink
Hallo,

als Gelegenheitsprogrammierer habe ich wieder mal ein Problem mit
dynamischen Arrays.

Ich binde eigene mit Delphi erzeugte DLL's dynamisch wie folgt in mein
Programm ein:

type
TSplProc = procedure
npspl(const n : integer; const y : array of double;
const d : double; const w : double;
var z : array of double); stdcall; // Delphi DLL
bzw. cdecl; // C++ DLL

procedure npspl (const n : integer; const y : array of double;
const d : double; const w : double;
var z : array of double);
var
Spl : TSplProc;
Handle : THandle;
begin
Handle:=LoadLibrary(PChar('spl.dll'));
if Handle<>0 then begin
@Spl:=GetProcAddress(Handle,'_npspl');
if @Spl<>nil then Spl(n,y,d,w,z);
FreeLibrary(Handle);
end;
end;

Mit Delphi-DLL's funktioniert das alles wunderbar, will ich aber eine
C++ DLL einbinden dann knallts zur Laufzeit.
Verwende ich statische Arrays, so funktionierts auch.
Was mache ich falsch bzw. wie muss ich es richtig machen ?
Oder geht das Ganze gar nicht mit dynamischen Arrays ?

Die C++ Prozedur hat folgenden Kopf:

void
npspl(unsigned long n, double y[], double d, double w, double z[])


Wäre schön wenn mir jemand helfen könnte.
Tschüß
Siggi
hsg
2006-01-18 07:15:36 UTC
Permalink
Hallo,

meines Wissens unterscheiden sich die Speicherstrukturen dynamischer
Arrays in C++ und Delphi gehörig (Delphi speichert an erster Stelle
des Speichers die Länge des Arrays ab), so dass das gar nicht gehen
kann. Besser du benutzt nur Pointer an der Stelle.

HTH
Jörg
Christian Gudrian
2006-01-18 08:19:37 UTC
Permalink
Post by Siegfried Jess
void
npspl(unsigned long n, double y[], double d, double w, double z[])
Oder geht das Ganze gar nicht mit dynamischen Arrays ?
Richtig. Delphi's dynamische Arrays bauen zu einem großen Teil auf
Compiler-Magie. Hinter den Kulissen passiert einiges mehr als das, was Du
im Quelltext schreibst. C++ kennt so eine Datenstruktur nicht.
Dementsprechend verwendet die Funktion auch ganz profane Arrays. Das
Gegenstück in Delphi wäre dann einfach ein Zeiger auf ein Double-Array
beliebiger Größe.

Bei C++-DLLs muss man übrigens aufpassen, dass beim Exportieren der
Funktionen kein name mangling durchgeführt wird und die Aufrufkonventionen
stimmen. Ansonsten kommt man von Delphi aus nur noch schwer bis gar nicht
mehr an die Funktion heran.

Gruß,

Christian
Daniel Albuschat
2006-01-18 08:22:48 UTC
Permalink
Post by Christian Gudrian
Post by Siegfried Jess
void
npspl(unsigned long n, double y[], double d, double w, double z[])
Oder geht das Ganze gar nicht mit dynamischen Arrays ?
Richtig. Delphi's dynamische Arrays bauen zu einem großen Teil auf
^
Ihr wisst beide schon, dass "DLL's" und "Delphi's" gleichermassen falsch
wie toericht ist?
Post by Christian Gudrian
Compiler-Magie. Hinter den Kulissen passiert einiges mehr als das, was Du
im Quelltext schreibst. C++ kennt so eine Datenstruktur nicht.
C++ kennt std::vector. Der benoetigt nichtmals Compilermagie dafuer.

MfG,
Daniel
Stefan M. Huber
2006-01-18 08:31:15 UTC
Permalink
On Wed, 18 Jan 2006 09:22:48 +0100, Daniel Albuschat
Post by Daniel Albuschat
Post by Christian Gudrian
Post by Siegfried Jess
Oder geht das Ganze gar nicht mit dynamischen Arrays ?
Richtig. Delphi's dynamische Arrays bauen zu einem großen Teil auf
^
Ihr wisst beide schon, dass "DLL's" und "Delphi's" gleichermassen falsch
wie toericht ist?
Und wenn du *nicht* aus der Schweiz bist, ist "gleichermassen" wohl eher
ein metrischer Vergleich von Körpern als ein Synonym für "genauso" :)
Post by Daniel Albuschat
Post by Christian Gudrian
Compiler-Magie. Hinter den Kulissen passiert einiges mehr als das, was Du
im Quelltext schreibst. C++ kennt so eine Datenstruktur nicht.
C++ kennt std::vector. Der benoetigt nichtmals Compilermagie dafuer.
Aus Neugier (Ich kenn C++ nicht): Meinst du damit, dass man das in
C++ ausprogrammiert, anstatt dem Compiler zu überlassen?

Stefan
--
Warum habe Enten Plattfüße?
Damit sie, wenn es brennt, das Feuer austreten können.
Warum haben Elefanten Plattfüße?
Damit sie brennende Enten austreten können.
Daniel Albuschat
2006-01-18 10:26:14 UTC
Permalink
Post by Stefan M. Huber
On Wed, 18 Jan 2006 09:22:48 +0100, Daniel Albuschat
Post by Daniel Albuschat
Ihr wisst beide schon, dass "DLL's" und "Delphi's" gleichermassen falsch
wie toericht ist?
Und wenn du *nicht* aus der Schweiz bist, ist "gleichermassen" wohl
eher ein metrischer Vergleich von Körpern als ein Synonym für "genauso" :)
Obwohl ich nicht aus der Schweiz bin, jedoch mein am haeufigsten
genutztes Eingabegeraet in der am haeufigsten genutzten Konfiguration
kein sz ausspuckt, darf ich auch "gleichermassen" schreiben.
Post by Stefan M. Huber
Post by Daniel Albuschat
Post by Christian Gudrian
Compiler-Magie. Hinter den Kulissen passiert einiges mehr als das,
was Du
im Quelltext schreibst. C++ kennt so eine Datenstruktur nicht.
C++ kennt std::vector. Der benoetigt nichtmals Compilermagie dafuer.
Aus Neugier (Ich kenn C++ nicht): Meinst du damit, dass man das in C++
ausprogrammiert, anstatt dem Compiler zu überlassen?
Nicht ausprogrammiert sondern ausprogrammieren laesst.
Von den Herstellern der Standardbibliothek, die man verwendet.
std::vector ist vergleichbar mit einer TList.
Die Philosophie, eine Kernsprache zu gestalten, in der Vieles auf
einfachem und elegantem Weg moeglich ist, weicht stark von Delphis
ab, die schon einfache Dinge wie Zeichenketten in die Kernsprache
einbaut, eine Semianalogie zu dynamischen Arrays aufbaut die verwirrend
und inkonsistent ist und generell wenig Anpassung an persoenliche
Beduerfnisse bietet.
Hans-Peter Diettrich
2006-01-19 06:01:50 UTC
Permalink
Post by Daniel Albuschat
Die Philosophie, eine Kernsprache zu gestalten, in der Vieles auf
einfachem und elegantem Weg moeglich ist, weicht stark von Delphis
ab, die schon einfache Dinge wie Zeichenketten in die Kernsprache
einbaut,
IMO gehören Strings schon zu den grundlegenden Datenstrukturen, ohne die
ein Compiler ja nicht einmal String-Literale verarbeiten kann. Oder wie
willst Du einem Compiler beibringen, welchen Datentyp aus welcher
Bibliothek er für solche Literale verwenden soll?

Andererseits vermisse ich bei Delphi/Pascal eine Unterscheidung zwischen
String- und Zeichenliteralen, wie das bei C mit einfachen bzw. doppelten
Apostrophen gemacht wird. Dieses Weglassen ist mir wieder etwas zu viel
Compiler-Magic. Auch die überkommene Konvention der String-Indizierung
ab 1 ist ein Beispiel für ein kurzsichtiges Sprachdesign :-(

Dafür mußte aber C aufgebohrt werden, um int64 und Unicode Strings in
die Sprache einzubauen - mit einer gräßlichen Syntax. Also sooo
universell ist das Konzept von C/C++ nun auch wieder nicht ;-)
Post by Daniel Albuschat
eine Semianalogie zu dynamischen Arrays aufbaut die verwirrend
und inkonsistent ist und generell wenig Anpassung an persoenliche
Beduerfnisse bietet.
Mit dieser Implementierung kann man durchaus leben, wenn man sie erst
einmal verinnerlicht hat - also kein Unterschied zu anderen
Programmiersprachen. Die fehlenden Anpassungsmöglichkeiten sehe ich
sogar als Vorteil, da dann nicht jeder sein eigenes inkompatibles
Süppchen kochen kann. An den Bibliotheken von C++ sollte ja auch keiner
herumpfuschen, um sie an seine perönlichen Bedürfnisse anzupassen? Und
ob die dortigen Klassen für Strings und deren Verarbeitung (I/O...)
wirklich den persönlichen Bedürfnissen aller entsprechen, das wage ich
aus meiner Erfahrung doch stark zu bezweifeln...

DoDi
Daniel Albuschat
2006-01-20 21:20:39 UTC
Permalink
Post by Hans-Peter Diettrich
Dafür mußte aber C aufgebohrt werden, um int64 und Unicode Strings in
die Sprache einzubauen - mit einer gräßlichen Syntax. Also sooo
universell ist das Konzept von C/C++ nun auch wieder nicht ;-)
C kennt kein UNICODE. C kennt nur die Unterscheidung zwischen wchar_t
und char. Und enstprechend natuerlich wchar_t* und char*.
Und dass das bei Stringliteralen angegeben werden muss, ist sehr
nuetzlich. Literale, dessen Typ sich aus dem Kontext ergibt, wie es in
Delphi der Fall sind, sind mehr als laestig.
Post by Hans-Peter Diettrich
An den Bibliotheken von C++ sollte ja auch keiner
herumpfuschen, um sie an seine perönlichen Bedürfnisse anzupassen? Und
ob die dortigen Klassen für Strings und deren Verarbeitung (I/O...)
wirklich den persönlichen Bedürfnissen aller entsprechen, das wage ich
aus meiner Erfahrung doch stark zu bezweifeln...
Um streams und strings in C++ anzupassen, kann man eigene streambuf
und stringbuf Klassen schreiben. Damit kann man z.B. strings
case-insensitive werden oder einen stream auf einem Socket arbeiten
lassen. Ersteres ist in Delphi nicht annaehernd moeglich, letzteres
nur durch Laufzeitpolymorphie.

MfG,
Daniel Albuschat
Hans-Peter Diettrich
2006-01-21 10:49:43 UTC
Permalink
Post by Daniel Albuschat
Post by Hans-Peter Diettrich
Dafür mußte aber C aufgebohrt werden, um int64 und Unicode Strings in
die Sprache einzubauen - mit einer gräßlichen Syntax. Also sooo
universell ist das Konzept von C/C++ nun auch wieder nicht ;-)
C kennt kein UNICODE. C kennt nur die Unterscheidung zwischen wchar_t
und char. Und enstprechend natuerlich wchar_t* und char*.
Und was sollte wchar_t sein, wenn nicht Unicode?
Post by Daniel Albuschat
Und dass das bei Stringliteralen angegeben werden muss, ist sehr
nuetzlich. Literale, dessen Typ sich aus dem Kontext ergibt, wie es in
Delphi der Fall sind, sind mehr als laestig.
Probleme sehe ich da nur bei der in Delphi fehlenden Unterscheidung
zwischen string und char Literalen. Der Typ des Ergebnisses eines
Ausdrucks hingegen ist dem Compiler bekannt, so daß er völlig
selbständig zwischen Ansi und Unicode umschalten kann.
Post by Daniel Albuschat
Post by Hans-Peter Diettrich
An den Bibliotheken von C++ sollte ja auch keiner herumpfuschen, um
sie an seine perönlichen Bedürfnisse anzupassen? Und ob die dortigen
Klassen für Strings und deren Verarbeitung (I/O...) wirklich den
persönlichen Bedürfnissen aller entsprechen, das wage ich aus meiner
Erfahrung doch stark zu bezweifeln...
Um streams und strings in C++ anzupassen, kann man eigene streambuf
und stringbuf Klassen schreiben. Damit kann man z.B. strings
case-insensitive werden oder einen stream auf einem Socket arbeiten
lassen. Ersteres ist in Delphi nicht annaehernd moeglich, letzteres
nur durch Laufzeitpolymorphie.
Pascal kennt zwar keine Templates, aber eine Nachbildung ist trotzdem
möglich.

Zudem hege ich immer noch den Verdacht, daß gerade die I/O von C/C++,
zusammen mit den Null-terminierten Strings, daran Schuld ist, daß der
Compiler so langsam ist.

DoDi

Christian Gudrian
2006-01-18 09:30:17 UTC
Permalink
Post by Daniel Albuschat
Ihr wisst beide schon, dass "DLL's" und "Delphi's" gleichermassen falsch
wie toericht ist?
Dass ein "'s" zur Kennzeichnung des Plural's falsch ist (und zwar auch in
angelsächsischen Ländern), ist klar. Aber töricht? Und ein "'s" zur
Kennzeichnung des Genitivs ist in Deutschland nur zur Vermeidung von
Missverständnissen erlaubt (Andreas vs. Andrea's). Somit stimme ich dir
insofern zu, als ich korrekterweise "Delphis" geschrieben haben müsste.

Mich allerdings in einen Topf mit den Plural-Apostrophisten zu werfen, nehme
ich dir nachhaltig übel.
Post by Daniel Albuschat
C++ kennt std::vector. Der benoetigt nichtmals Compilermagie dafuer.
Und? Der Builder kennt ebenfalls ein DynamicArray-Template, mit dem das
dynamische Array von Delphi emuliert wird. Das tolle an Delphi ist
allerdings, dass Strings und dynamische Arrays bereits Teil der Sprache
selbst sind ("string" und "array of" sind Schlüsselwörter) und nicht erst
durch Klassenbibliotheken bereitgestellt werden müssen.

Christian
Daniel Albuschat
2006-01-18 10:20:21 UTC
Permalink
Post by Christian Gudrian
Post by Daniel Albuschat
Ihr wisst beide schon, dass "DLL's" und "Delphi's" gleichermassen falsch
wie toericht ist?
Mich allerdings in einen Topf mit den Plural-Apostrophisten zu werfen, nehme
ich dir nachhaltig übel.
Alles dasselbe Pack! ;-)
Post by Christian Gudrian
Post by Daniel Albuschat
C++ kennt std::vector. Der benoetigt nichtmals Compilermagie dafuer.
Und? Der Builder kennt ebenfalls ein DynamicArray-Template, mit dem das
dynamische Array von Delphi emuliert wird. Das tolle an Delphi ist
allerdings, dass Strings und dynamische Arrays bereits Teil der Sprache
selbst sind ("string" und "array of" sind Schlüsselwörter) und nicht erst
durch Klassenbibliotheken bereitgestellt werden müssen.
Was ist daran toll?
Christian Gudrian
2006-01-18 10:28:18 UTC
Permalink
Post by Daniel Albuschat
Alles dasselbe Pack! ;-)
7-Bit-Fetischist!
Post by Daniel Albuschat
Was ist daran toll?
Wenn's dir nicht gefällt, geh' doch zu den C++lern. Die Apostrophen sind
hier übrigens richtig.

Christian
Daniel Albuschat
2006-01-18 10:32:55 UTC
Permalink
Post by Christian Gudrian
Post by Daniel Albuschat
Alles dasselbe Pack! ;-)
7-Bit-Fetischist!
Entweder 7 Bit oder UTF-8.
Aber ich verstehe die Anmerkung nicht ganz.
Post by Christian Gudrian
Post by Daniel Albuschat
Was ist daran toll?
Wenn's dir nicht gefällt, geh' doch zu den C++lern. Die Apostrophen sind
hier übrigens richtig.
a) Die Frage war ernst gemeint.
b) Meine C++ Kenntnisse gleichen meinen Delphi Kenntnissen.
c) Mein Job verlangt Delphi Kenntnisse.
Hans-Peter Diettrich
2006-01-18 10:47:59 UTC
Permalink
Post by Christian Gudrian
Post by Daniel Albuschat
C++ kennt std::vector. Der benoetigt nichtmals Compilermagie dafuer.
Und? Der Builder kennt ebenfalls ein DynamicArray-Template, mit dem das
dynamische Array von Delphi emuliert wird. Das tolle an Delphi ist
allerdings, dass Strings und dynamische Arrays bereits Teil der Sprache
selbst sind ("string" und "array of" sind Schlüsselwörter) und nicht erst
durch Klassenbibliotheken bereitgestellt werden müssen.
Das schöne an Klassenbibliotheken ist zumindest, daß diese pro Compiler
unterschiedlich implementiert sein können. Eine DLL kann somit eine
andere Definition verwenden als das aufrufende Programm, und dann ist
die Kacke am Dampfen :-(


Die beste Kompatibilität läßt sich IMO immer noch mit den Techniken von
C erreichen, für (eindimensionale!) Arrays ein Pointer auf das erste
Element, und zusätzlich die Anzahl der Elemente übergeben.

DoDi
Daniel Albuschat
2006-01-18 08:20:05 UTC
Permalink
Post by Siegfried Jess
Hallo,
als Gelegenheitsprogrammierer habe ich wieder mal ein Problem mit
dynamischen Arrays.
Ich binde eigene mit Delphi erzeugte DLL's dynamisch wie folgt in mein
type
TSplProc = procedure
npspl(const n : integer; const y : array of double;
const d : double; const w : double;
var z : array of double); stdcall; // Delphi DLL
bzw. cdecl; // C++ DLL
void
npspl(unsigned long n, double y[], double d, double w, double z[])
Wäre schön wenn mir jemand helfen könnte.
TSplProc = procedure
npspl(const n : cardinal; const y : PDouble;
const d : double; const w : double;
var z : PDouble); stdcall; // Delphi DLL
bzw. cdecl; // C++ DLL
Die Strukturen von offenen Array-Parametern in Delphi haben nichts mit
Arrays in C und C++ zu tun.
In C/C++ ist ein Array einfach nur ein Pointer auf das erste Element.
Dementsprechend musst du dann Pointer in Delphi benutzen.
Auf Element x des Arrays greifst du dann mit
PDouble(Cardinal(y)+Index*sizeof(Double))^ zu.

Und lass C++ lieber links liegen, wenn du nichtmals Arrays verstehst.
Ist n die Anzahl der Elemente in y und z? Wenn nicht, musst du
natuerlich noch die Anzahl der Elemente in y und z uebergeben.
Von alleine kann dein Computer die nicht erraten.

MfG,
Daniel
Siegfried Jess
2006-01-18 09:31:58 UTC
Permalink
Post by Daniel Albuschat
Post by Siegfried Jess
TSplProc = procedure
npspl(const n : cardinal; const y : PDouble;
const d : double; const w : double;
var z : PDouble); stdcall; // Delphi DLL
bzw. cdecl; // C++ DLL
Die Strukturen von offenen Array-Parametern in Delphi haben nichts mit
Arrays in C und C++ zu tun.
In C/C++ ist ein Array einfach nur ein Pointer auf das erste Element.
Dementsprechend musst du dann Pointer in Delphi benutzen.
Auf Element x des Arrays greifst du dann mit
PDouble(Cardinal(y)+Index*sizeof(Double))^ zu.
Danke für diesen Hinweis, werde das mal probieren.
Post by Daniel Albuschat
Und lass C++ lieber links liegen, wenn du nichtmals Arrays verstehst.
C++ liegt bei mir ganz weit links, aber ich habe eben nur die DLL die in
C geschrieben ist zur Verfügung.
Post by Daniel Albuschat
Ist n die Anzahl der Elemente in y und z? Wenn nicht, musst du
natuerlich noch die Anzahl der Elemente in y und z uebergeben.
Von alleine kann dein Computer die nicht erraten.
Ja, ist klar. n ist die Anzahl der Elemente in y und z.

MfG
Siggi
Loading...