Problem mit "machine generated header"



  • Hallo.

    Ich füge in mein Projekt eine neu hinzugefügte Komponente ein. Wenn ich das Projekt compilieren möchte, dann erhalte ich diverse Fehlermeldungen:

    [BCC32 Fehler] Vectorgeometry.hpp(378): E2356 Redeklaration von '_fastcall VectorAdd(const float *,const float )' mit anderem Typ
    // extern PACKAGE Vectortypes::TVector4f __fastcall VectorAdd(float const *v1, float const *v2)/
    overload */;

    [BCC32 Fehler] Vectorgeometry.hpp(375): E2344 '_fastcall VectorAdd(const float *,const float )' bereits deklariert
    // extern PACKAGE Vectortypes::TVector3f __fastcall VectorAdd(float const *v1, float const *v2)/
    overload */;

    oder

    [BCC32 Fehler] Vectorgeometry.hpp(406): E2316 'PSingle' ist kein Element von 'System'
    // extern PACKAGE void __fastcall CombineVector(float *vr, float const *v, System::PSingle pf)/* overload */;

    Diese Eigenschaft gibt es aber: http://docwiki.embarcadero.com/Libraries/de/System.PSingle
    Wenn ich "System::" entfernt, ist dieser Fehler auch weg. Ich verstehe aber nicht warum dies nicht mit "System::" geht.

    Ansonsten entdecke ich auch oft identische Funktionen untereinander, in der "machine generated header":

    void __fastcall Translate(float const *translationVector)/* overload */;
    void __fastcall Translate(float const *translationVector)/* overload */;
    void __fastcall AddScaledVector(const float factor, float const *translationVector)/* overload */;
    void __fastcall AddScaledVector(const float factor, float const *translationVector)/* overload */;
    void __fastcall Rotate(float const *anAxis, float anAngle)/* overload */;
    void __fastcall Rotate(float const *anAxis, float anAngle)/* overload */;

    [BCC32 Fehler] GLCoordinates.hpp(91): E2062 Unzulässiger Indirektionsoperator
    // __property float X = {read=FCoords[8], write=SetCoordinate, index=0};

    Kann zu diesen Fehlern jemand etwas sagen? Fehlte eventuell eine Option beim compilieren der Komponente?

    Ich verwende das "Rad Studio 2009".



  • PSingle hat jemand wohl als $EXTERNALSYM deklariert (d.h. es wird keine Deklaration in den Header ausgegeben), zugleich aber vergessen, die Deklaration manuell in sysmac.h einzufügen.

    Die Mehrdeutigkeitsfehler rühren daher, daß Delphi Typen mit verschiedenen Namen als unterschiedlich betrachtet:

    type
      TMyInt = Integer;
      TYourInt = Integer;
    
    procedure Foo (Int: TMyInt); overload;
    procedure Foo (Int: TYourInt); overload;
    

    Das geht in C++ nicht; typedef erspart nur Schreibarbeit, schafft aber keinen neuen Typen. Da GLScene diese Eigenart von Delphi vielfach nutzt, sind die jeweiligen Headerdateien inkompatibel mit dem C++Builder.



  • Danke für die sehr gute Erklärung. Jetzt verstehe ich auch mehr das Grundproblem.

    Dies gilt im C++Header als identisch:

    extern PACKAGE Vectortypes::TVector3f __fastcall VectorSubtract(float const *v1, float delta)/* overload */;
    extern PACKAGE Vectortypes::TVector4f __fastcall VectorSubtract(float const *v1, float delta)/* overload */;
    

    Delphi Definition:

    TVector3f = array[0..2] of single;
    TVector4f = array[0..3] of single;
    

    C++Header Definition:

    typedef StaticArray<float, 3> TVector3f;
    typedef StaticArray<float, 4> TVector4f;
    

    C++ kann dies nicht unterscheiden, da typedef kein echter Datentyp ist? Da gibt es auch keinen Trick?



  • NewComp schrieb:

    Dies gilt im C++Header als identisch:

    extern PACKAGE Vectortypes::TVector3f __fastcall VectorSubtract(float const *v1, float delta)/* overload */;
    extern PACKAGE Vectortypes::TVector4f __fastcall VectorSubtract(float const *v1, float delta)/* overload */;
    

    Ja, bzw. als mehrdeutig, weil es als (unzulässige) Überladung via Rückgabetyp betrachtet wird.

    NewComp schrieb:

    Delphi Definition:

    TVector3f = array[0..2] of single;
    TVector4f = array[0..3] of single;
    

    C++Header Definition:

    typedef StaticArray<float, 3> TVector3f;
    typedef StaticArray<float, 4> TVector4f;
    

    Die sind natürlich unterschiedlich. StaticArray<float, 3> ist was anderes als StaticArray<float, 4> , also ist auch TVector3f was anderes als TVector4f . Aber wenn irgendwo in GLScene noch

    type
      TColorVector = TVector4f;
    

    steht, dann ist TColorVector in Delphi was anderes als TVector4f , in C++ allerdings nicht, da nur typedef desselben Typs.

    NewComp schrieb:

    C++ kann dies nicht unterscheiden, da typedef kein echter Datentyp ist? Da gibt es auch keinen Trick?

    Nein, nur Workarounds.

    Die richtige Lösung wäre, den GLScene-Quelltext C++Builder-kompatibel zu machen und dazu alle redundanten Überladungen zu entfernen. Das gefällt aber den Delphi-Benutzern nicht, weil dann ihre Programme nicht mehr ohne Änderungen kompilieren.

    Ein möglicher Workaround wäre, alle betroffenen Funktionen mit $EXTERNALSYM aus dem Header auszusperren. Das war mir viel zu viel Aufwand, und außerdem hat man das Problem dann, inklusive des andauernden manuellen Zusammenführens, bei jedem svn update .

    Der produktivste, am besten unterstützte Weg ist, GLScene in Delphi zu wrappen und die Wrapperkomponente in C++ zu benutzen. Das mache ich, es geht gut und nervt nur ein ganz kleines bißchen.

    Die zahlreichen Überladungen sind selbst Workarounds für diese hier offensichtlich hinderliche Eigenschaft von Delphi. Idealerweise hätte Delphi diese bescheuerte Eigenart gar nicht.



  • audacia schrieb:

    Die richtige Lösung wäre, den GLScene-Quelltext C++Builder-kompatibel zu machen und dazu alle redundanten Überladungen zu entfernen. Das gefällt aber den Delphi-Benutzern nicht, weil dann ihre Programme nicht mehr ohne Änderungen kompilieren.

    Wäre auch zu schön...

    audacia schrieb:

    Ein möglicher Workaround wäre, alle betroffenen Funktionen mit $EXTERNALSYM aus dem Header auszusperren. Das war mir viel zu viel Aufwand, und außerdem hat man das Problem dann, inklusive des andauernden manuellen Zusammenführens, bei jedem svn update.

    Ich habe mal versucht mich darüber zu informieren. So wirklich verstanden, wie man das in diesem Fall hier korrekt einsetzt, habe ich das aber bis jetzt leider noch nicht. Könntest du eventuell da ein bis zwei Beispiele geben? *liebguck*
    http://docwiki.embarcadero.com/RADStudio/de/Externe_Symbole_(Delphi)
    http://docwiki.embarcadero.com/Libraries/XE3/de/API:System.Types.cPI
    Schade das sie keinen C++Wrapper anbieten. Ich verstehe dann aber nicht wieso es "Borland C++Builder" Beispiele in der Source gibt. Das muss ja mal zu BCB5+6 Zeiten funktioniert haben.

    audacia schrieb:

    Der produktivste, am besten unterstützte Weg ist, GLScene in Delphi zu wrappen und die Wrapperkomponente in C++ zu benutzen. Das mache ich, es geht gut und nervt nur ein ganz kleines bißchen.

    GLScene selbst ist ja ein Wrapper für OpenGL. Ich habe da leider zu wenig Erfahrung mit Delphi um das "einfach mal so" auf diese Art und Weise zu lösen. Da könnte ich anschließend vermutlich gleich auf Delphi umsteigen. Ich mag den Syntax von Delphi aber eher weniger. Da ich auch in PHP rumprogrammiere, liegt mir C eher als Pascal. 😉

    Schade das FireMonkey 3D so erbärmlich im Umfang seiner 3D Funktionen ist. Ich kann echt nicht nachvollziehen wie man das so rotz frech als "for business" anbieten kann und dann als Betatester den Kunden missbraucht. Aber das scheint ja mittlerweile Tradition bei Anwendungen zu werden.

    audacia schrieb:

    Die zahlreichen Überladungen sind selbst Workarounds für diese hier offensichtlich hinderliche Eigenschaft von Delphi. Idealerweise hätte Delphi diese bescheuerte Eigenart gar nicht.

    Ich kann mich nicht wirklich entscheiden ob ich dies als ein cooles Feature ansehen soll, oder nicht. ^^



  • NewComp schrieb:

    So wirklich verstanden, wie man das in diesem Fall hier korrekt einsetzt, habe ich das aber bis jetzt leider noch nicht. Könntest du eventuell da ein bis zwei Beispiele geben? *liebguck*

    Der RTL-Quelltext ist voll davon, außerdem ist das doch völlig trivial, was gibts daran nicht zu verstehen?

    {$EXTERNALSYM MehrdeutigeFunktion} // => Funktion wird nicht in Header ausgegeben
    

    NewComp schrieb:

    Schade das sie keinen C++Wrapper anbieten. Ich verstehe dann aber nicht wieso es "Borland C++Builder" Beispiele in der Source gibt. Das muss ja mal zu BCB5+6 Zeiten funktioniert haben.

    Ja, wahrscheinlich war das so, und zwischenzeitlich ist es abgedriftet. Die offizielle Seite behauptet, glaube ich, auch noch "... for Delphi and C++Builder".

    NewComp schrieb:

    Ich habe da leider zu wenig Erfahrung mit Delphi um das "einfach mal so" auf diese Art und Weise zu lösen. Da könnte ich anschließend vermutlich gleich auf Delphi umsteigen.

    Jetzt hab dich mal nicht so 😉 Delphi ist nicht schwer, als C++Builder-Programmierer kennst du die Kernelemente sowieso und außerdem sollte man Delphi zumindest lesen können, wenn man C++Builder benutzt, weil man sonst viel zu oft bei Problemen mit 3rd-party-Komponenten aufgeschmissen ist (wie du jetzt). Nimm dir halt ein paar Tage Zeit für ein Tutorial über Komponenten in Delphi. Fragen darfst du gerne hier stellen.

    Oder wir fangen andersrum an. Was genau brauchst du denn aus GLScene? Ein oder zwei spezielle Komponenten, oder ganz viele? Willst du eine Scene zur Designzeit mit dem Editor zusammenbauen, oder passiert das eher zur Laufzeit?

    NewComp schrieb:

    Ich mag den Syntax von Delphi aber eher weniger.

    Die Syntax. Und Syntax ist nun wirklich das letzte, was dich an einer Sprache stören sollte (speziell wenn du so ein Syntaxmonster wie C++ benutzt).



  • Ich wollte erstmal einfach ausprobieren und 3D Linien, 3D Punkte und Objekte per Runtime zusammenstellen und animieren. Zur Designzeit benötige ich da eigentlich nichts. Eventuell sollte ich einfach mit OpenGL anfangen und mich dort einarbeiten? Ich hätte nur angenommen das GLScene da diverse wichtige Optimierungen drin hat, damit die Darstellung in der TForm möglichst optimal geschieht. Ich würde hier ziemlich von 0 anfangen.

    Per GLScene in Delphi reichen ein paar Zeilen und man hat was man will. Wirklich schade das die FireMonkey-Macher sich nicht mehr an GLScene orientiert haben. FireMonkey fehlen ja so ziemlich alle Basic-Feature die man in einer 3D Umgebung erwartet.



  • NewComp schrieb:

    Ich wollte erstmal einfach ausprobieren und 3D Linien, 3D Punkte und Objekte per Runtime zusammenstellen und animieren. Zur Designzeit benötige ich da eigentlich nichts.

    Okay, dann sind deine Anforderungen wirklich recht anders als die meinigen; ich wußte schon, was ich brauchte, und ich wollte nur eine sehr beschränkte Untermenge an Komponenten.

    Du könntest das entweder in Delphi machen (schaffst du schon 😉 es gibt ja auch zahlreiche Beispiele, und viele Dinge sind in Delphi viel einfacher/schöner als in C++), etwas C++-artigeres benutzen (SFML oder so, keine Ahnung) oder eben GLScene so lange massieren, bis du es im C++Builder verwenden kannst. Aber selbst wenn du das geschafft haben solltest, wird die Kompilierzeit wird schwer beeinträchtigt, wenn du all die GLScene-Header einbinden mußt. Und in der Zeit, die du dann auf den Compiler warten mußt, hättest du auch Delphi lernen können 😉


Anmelden zum Antworten