Nicht TForm-Objekt aus BPL erzeugen



  • Hallo zusammen,

    zum Erzeugen von Objekten deren Klassen in BPLs definiert sind, verwende ich folgenden Mechanismus:

    THandle PackageHandle = LoadPackage("Package");
    TClass UnitClass = GetClass("TForm1");
    TForm1 *Form1;
    Application->CreateForm(UnitClass, &Form1);
    

    Auf diese Art kann ich aber nur Instanzen von Klassen erzeugen, die von TForm
    abgeleitet sind, will aber auch andere Klassen verwenden.

    Es müsste also eine Alternative für Application->CreateForm() her...

    Leider komme ich an diesem Punkt nicht weiter und bin mir auch nicht ganz sicher ob das überhaupt möglich ist. Hoffe ihr könnt mir helfen.



  • Ich vermute mal, daß du das etwas anders meinst, aber wenn deine Anwendung die Klassen wie in deinem Beispiel bereits kennt, kannst du einfach new benutzen:

    TForm1 *Form1 = new TForm1 (Application);
    

    Oder ist die aus dem Package importierte Klasse, hier TForm1, in deiner Anwendung gar nicht bekannt, so daß dein Code nur die nächstgelegene Basisklasse benutzen kann:

    THandle PackageHandle = LoadPackage ("Package");
    TClass UnitClass = GetClass ("TForm1");
    TForm *Form1; // <--
    Application->CreateForm (UnitClass, &Form1);
    

    ?



  • Deine zweite Vermutung stimmt genau, aber ich versuch mich etwas konkreter auszudrücken 🙂

    Die Anwendung importiert die Klassendefinition (.h) von TForm1 (bzw die Basisklasse) per #include. Der Quellcode (.cpp) befindet sich aber nur in der BPL.

    Da TForm1 bei der Initialisierung mit

    RegisterClass(__classid(TForm1))
    

    registriert wurde, kann ich ja aus der EXE heraus mit CreateForm ein Objekt von TForm1 erzeugen. CreateForm funktioniert aber nur in Verbindung mit Formularen, ich möchte aber auch gerne Nicht-Formular-Klassen verwenden.



  • In C++ gibt es leider nur sehr eingeschränkte Unterstützung für Klassenreferenzen: diese sind anders als in Delphi nur schwach typisiert, d.h. wo du in Delphi class of TComponent hast, gibt es in C++ nur TClass . Deshalb kann man auch keine Klassenfunktionen oder virtuelle Konstruktoren über Klassenreferenzen aufrufen, jedenfalls nicht direkt.

    Da es in Delphi möglich ist, virtuelle Konstruktoren aufzurufen, kannst du deinem Projekt folgendes Delphi-Unit hinzufügen:

    unit Activator;
    
    interface
    
    (*$HPPEMIT END 'namespace Activator {'*)
    (*$HPPEMIT END ''*)
    (*$HPPEMIT END 'template <typename Obj>'*)
    (*$HPPEMIT END '    Obj* CreateComponent (TClass ClassRef, TComponent* Owner)'*)
    (*$HPPEMIT END '{'*)
    (*$HPPEMIT END '    return dynamic_cast<Obj*> (Activator::CreateComponent (ClassRef, Owner));'*)
    (*$HPPEMIT END '}'*)
    (*$HPPEMIT END ''*)
    (*$HPPEMIT END '} // namespace Activator'*)
    
    uses
      Classes;
    
    function CreateComponent (ClassRef: TComponentClass; Owner: TComponent): TComponent;
    
    implementation
    
    function CreateComponent (ClassRef: TComponentClass; Owner: TComponent): TComponent;
    begin
      Result := ClassRef.Create (Owner); // das geht in C++ nicht
    end;
    
    end.
    

    In C++ kannst du das dann folgendermaßen benutzen:

    #include "Activator.hpp"
    
    ...
        THandle PackageHandle = LoadPackage ("Package");
        TClass UnitClass = GetClass ("TForm1");
        TForm* Form1 = CreateComponent<TForm> (UnitClass, theOwner);
    


  • Vielen Dank für deinen Beitrag 👍

    Ich hatte schon vermutet, dass das in C++ nicht gehen wird.
    Aber deine Lösung gefällt mir sehr gut.


Log in to reply