![]() |
Header Generator: eigenen Typ übernehmen
Hallo zusammen!
Ich habe mal wieder eine Frage und wollte mich bei euch vergewissern, dass ich nicht noch was übersehen habe, bevor ich dann einen QC Eintrag dazu eröffne. Einführung & Problem Es ist bekannt, dass der UInt64 nur halbherzig unterstützt wird und leider nie richtig durchgezogen wurde. In Delphi selbst ist es soweit ein fast nutzbarer Typ und auf C++ Seite steht dem ein unsigned __int64 zur Seite. Nun ist es aber ein Problem, wenn man beide Sprachen zusammen in einem Projekt nutzt. Grundlegend wird UInt64 gebraucht, da die Werte grösser als $7fffffffffffffff werden und somit uns das invertieren durch das Vorzeichen in die Seite haut. Es ist ein bekanntes Problem, dass eine UInt64 Deklaration in einer Pascalquelle vom Header (.hpp) Generator falsch in ein __int64 übersetzt wird ( ![]() ![]() Ok, nun, da hat man ein Problem. Der Umweg über den nicht berechenbaren Struct (z.B. Int64Rec, TFileTime, etc) wollten wir definitiv nicht gehen und somit musste eine andere Lösung her. Lösungen Die bisherigen Lösungen: 1. Man ändert immer nach deren Generierung die Header files ab zu den jeweiligen Pascal Quellen zu einer unsigned __int64 Deklaration, so dass der Linker und Compiler glücklich sind. 2. Man nutzt andere Typen wie z.B. einen Record um die Daten zu übergeben (z.B. Int64Rec, TFileTime, etc). 3. Man definiert einen Linker Alias Eintrag #pragma alias "@unit@class@method$typelist@resulttype"="@unit@cl ass@method$typelist@resulttype" Beim Lösung 1 und 3 muss jeder Autor, welcher UInt64 nutzen will, eine extra Zeile bzw Aufwand betreiben, damit im Buildskript (1. Lösung) bzw. in der Quelle die richtigen zusätzlichen Angaben gemacht werden. Dies lässt sich somit für nicht-Programmierer schwer durchsetzen, vor allem die 3. Lösung benötigt schon einen gewissen Aufwand und Wissen. Die erste Lösung ist in der IDE nicht praktizierbar und die zweite Lösung fällt aufgrund des unhandlichen Typs weg. So kam nun die Idee auf vorhandene Möglichkeiten zurück zu greifen: Borland bietet mit $NODEFINE, $EXTERNALSYM und $HPPEMIT eine recht interessante Möglichkeit die Headergenerierung zu beeinflussen. Somit haben wir uns einfach dazu entschlossen einen neuen Typ zu definieren. Dieser wird dann anstatt des UInt64 benutzt und somit würde jeder auf die Nase fallen, der nicht den Typ benutzt (Linker kann nicht auflösen) und wir haben einen Typ der auf beiden Seiten bekannt ist und somit aufgelöst werden kann. Also entstand folgende kleine Pascal Datei:
Delphi-Quellcode:
(Die $Z4 kann man getrost ignorieren, aber in der C++/Delphi Mischprojektumgebung gibt es einen Bug, dass die Pascaloptionen nicht mehr an implizit angezogene Pascalquellen angewendet werden. Dazu wird noch ein QC Eintrag geschrieben werden)
unit FixUInt64;
{$Z4} interface type TFixUINT64 = type UInt64; implementation end. Daraus macht der Header Generator (leider erfahrungsgemäß):
Code:
... also den falschen Typ. Somit bekommt der Linker mit dem Typ wieder ein Problem. Somit: selbst deklarieren:
typedef __int64 TFixUINT64;
Delphi-Quellcode:
Ok, somit kommt schonmal das gewünschte Ergebnis in den Header:
unit FixUInt64;
{$Z4} interface type TFixUINT64 = type UInt64; {$EXTERNALSYM TFixUINT64} {$NODEFINE TFixUINT64} {$HPPEMIT 'typedef unsigned __int64 TFixUINT64;'} implementation end.
Code:
. Nun ist diese Hürde genommen, also losarbeiten:
typedef unsigned __int64 TFixUINT64;
Delphi-Quellcode:
Eigentlich alles super. Von Delphi Seite nutzbar, aber bei C++....
unit PasInterfaceImpl;
{$Z4} interface uses FixUInt64; function UseUint64( const param: TFixUINT64 ): TFixUINT64; implementation function UseUint64(const param: TFixUINT64): TFixUINT64; begin result := param; end; end. Nun ja, der Header Generator macht folgendes draus:
Code:
Also wieder der unbrauchbare Int64 Typ.
extern PACKAGE __int64 __fastcall UseUint64(const __int64 param);
Der Fehler? Der Fehler liegt hier zum einen in der bekannten falschen Umsetzung des UInt64 auf __int64. Aber das wollten wir ja mit dem neuen Typ umgehen. Das eigentliche Problem ist eher, dass ich mit der Deklaration in der Pascal Quelle extra kein Alias angelegt habe sondern definitiv einen neuen Typ (das zusätzliche type Keyword bei der Deklaration) und somit verstehe ich nicht, wie der Header Generator diesen zwar übernimmt aber ihn bei seiner Nutzung nicht entsprechen übernimmt. Der neue Typ ist definiert und wird explizit von der Funktion genutzt und er kann ihn so 1:1 übertragen, tut dies aber nicht. Hätte ich nicht einen neuen Typ sondern einen Alias angelegt, kann ich es verstehen, dass er zum Basistyp zurückkehrt, aber nicht, wenn ich einen explizit neuen Typ anlege. Ich sehe hier den Fehler darin, dass er diesen Typ nicht überträgt. Bei den einfachen Funktionen könnte man auch mit $NODEFINE und $HPPEMIT arbeiten, nicht aber bei Methoden, da dort nur die gesamte Klassendeklaration nicht übernommen werden kann, nicht aber einzelne Methoden. Die Frage Kennt ihr noch andere mögliche Lösungen bzw. gibt es noch weitere Angaben oder Schlüsselwörter, die den Header Generator zur Mitarbeit überreden lassen? Seine Automatismen bzw. Anpassungen vllt. mal zu unterlassen? /EDIT: Beschriebenes Problem bezieht sich auf das BDS2006! Bisher besteht gleiches Problem aber noch bei RAD2007, die Lösung wird aber für BDS2006 gesucht. |
Re: Header Generator: eigenen Typ übernehmen
Zitat:
Jedoch wird sich an der Tatsache, daß es kein C++Builder-Äquivalent zu Delphis "Strong Typedef"-Variante gibt, vermutlich nichts ändern, als bis eine solche endlich im C++-Standard festgelegt wurde. Dies wurde längst vorgeschlagen und wird nicht nur von CodeGear sehnlichst erwartet, aber offenbar scheint das Komitee sich mit der Bearbeitung dieses Problemes noch Zeit zu lassen: wie aus ![]() ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:21 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz