Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi DLL Parser Plugins (https://www.delphipraxis.net/144737-dll-parser-plugins.html)

Alaitoc 15. Dez 2009 13:49


DLL Parser Plugins
 
Hallo zusammen,

ich habe mehrere Parser, die ich mir je nach Datei über eine Factory erstelle und wo ich dann
ein Interface mit einem Execute()-Befehl zurückgebe.

Ich würde mir nun wünschen, dass ich diese Struktur in Plugins auslagere. Also das für jeden Dateityp ein Plugin vorhanden ist.
Über die Suche habe ich zwar das Tutorial von Sakura gefunden, jedoch braucht man dafür ShareMem.
Was gibt es für Möglichkeiten bzw gibt es Möglichkeiten ohne ShareMem?

MfG Alaitoc

himitsu 15. Dez 2009 14:00

Re: DLL Parser Plugins
 
Zitat:

Möglichkeiten ohne ShareMem?
Indem man alles NICHT verwendet, welches auf den Delphi-Speichermanager setzt.

keine dynamischen Arrays, keine String, AnsiString, UnicodeString und ähnliches

(WideString läuft über den Speichermanager der OleAuth.dll)

Mithrandir 15. Dez 2009 14:13

Re: DLL Parser Plugins
 
Wenn man ein wenig Vorbildung in ANSI-C hat, ist es gar nicht soooo schwer, ohne Strings und Co. zurecht zu kommen. Man muss nur dran denken, selbst genug Speicher anzufordern, und ihn auch wieder freizugeben (bevor man den Zeiger darauf vernichtet hat. :mrgreen: ).

Und denk dir bloß eine Dateiendung aus. "dll" treibt einigen Zeitgenossen die Schweißperlen auf die Stirn... :tongue:

Alaitoc 15. Dez 2009 14:22

Re: DLL Parser Plugins
 
Da ich den Begriff ShareMem noch nie gehört hatte und da es extra erwähnt wurde...dachte ich
das es eine externe Unit ist... :wall: :wall: :wall:

Ich schau mir mal das Tutorial von Sakura nochmal genauer an ^_°

MfG Alaitoc

Mithrandir 15. Dez 2009 14:36

Re: DLL Parser Plugins
 
Dir muss aber klar sein, dass du nicht nur die Unit einbinden musst, sondern auch die entsprechende dll (Name vergessen) mitliefern musst.

Außerdem schließt du so auch andere Sprachen, primär C/C++ aus, was ja gerade der Vorteil an dlls sein soll. ;)

Alaitoc 15. Dez 2009 14:43

Re: DLL Parser Plugins
 
Naja zuerst hatte ich es mit DLL+ versucht, jedoch
gab es da irgendein Problem. Ich glaube weil ich bisher noch Objekte als Übergabeparameter ( zur Ausgabe ) habe, das
dürfte so nicht klappen... :gruebel:

Wahrscheinlich muss ich mir da auch noch Gedanken zur Struktur machen und die dementsprechend überarbeiten... :|

Mithrandir 15. Dez 2009 14:46

Re: DLL Parser Plugins
 
Was C und Delphi gemeinsam haben, sind Records (in C heißen die halt structs). Zeiger darauf kann man problemlos zwischen DLLs austauschen. So realisiere ich gerade eine generische Pluginsschnittstelle für meinen kleinen Audioplayer...

Alaitoc 15. Dez 2009 14:53

Re: DLL Parser Plugins
 
Ah Danke, werde mal schauen ob ich meins so umstrukturieren kann( Ich hoffe ^^ )
und ob der Aufwand nicht allzu groß ist.

MfG Alaitoc

MarioM. 15. Dez 2009 15:21

Re: DLL Parser Plugins
 
Zitat:

Zitat von Daniel G
Und denk dir bloß eine Dateiendung aus. "dll" treibt einigen Zeitgenossen die Schweißperlen auf die Stirn... :tongue:

Sei vorsichtig; wenn R0815 das liest, bezichtigt er Dich gleich als beleidigend und jagt Dir den Cheffe auf den Hals. Da bist Du Deinen Mod-Status schneller los, als Dir recht ist :zwinker:

Zum Thema:
Super danke; ich stehe gerade vor einem ähnlichen Problem und kann mit der Hilfestellung gut was anfangen :)

Elvis 15. Dez 2009 18:14

Re: DLL Parser Plugins
 
Hehe, plugins + Interfaces sind so eine Pet-Disciplin von mir... ;-)

Generell ist es bei sowas immer gut, sich auf das u beschränken, was auch über COM funktioniert.
Also...
  • Keine Delphi-Stirng, dafür gehen WideStrings.
  • Keine Klassen, dfür gehen Interfaces.
  • Keine dynamischen Arrays, du kannst hierfür Listenklassen nehmen, die ein Interface implementieren.

Wenn du Interfaces nutzt[1], dann denke daran, dasss sie sich wenigstens ein bissel wie COM-Objekte benehmen sollten.
Das heißt alle Methoden sollte als Calling convention "safecall" nehmen, und alle sollten eine eindeutige GUID haben.


Hier mal ein Bleistift:
Solche eine DLL in Delphi, wäre so interoperabel, dass man sie sogar in C# nutzen könnte.

Delphi-Quellcode:
library SampleInterfaceDLL;

uses
  Dialogs;

type
  ISample = interface(IUnknown)
  ['{C9B334E4-BDAE-419E-9305-143B2C454CEA}']
    function Get_Value : WideString; safecall;
    procedure Set_Value(const value : WideString); safecall;

    procedure ShowValue; safecall;
    property Value : WideString
      read Get_Value
      write Set_Value;
  end;

  TSample = class(TInterfacedObject, ISample)
  private
    fValue : WideString;
    function Get_Value: WideString; safecall;
    procedure Set_Value(const aValue: WideString); safecall;
  public
    procedure ShowValue; safecall;
    property Value : WideString
      read Get_Value
      write Set_Value;
  end;

procedure CreateSample(out instance : ISample); stdcall;
begin
  instance := TSample.Create();
end;

function GetValueLength(const instance : ISample) : Integer; stdcall;
begin
  result := Length(instance.Value);
end;

exports
  GetValueLength,
  CreateSample;

{ TSample }

function TSample.Get_Value: WideString;
begin
  result := fValue;
end;

procedure TSample.Set_Value(const aValue: WideString);
begin
  fValue := aValue;
end;

procedure TSample.ShowValue;
begin
  ShowMessage('From Delphi: ' + Value);
end;

end.
Code:
[ComVisible(true)]
[Guid("C9B334E4-BDAE-419E-9305-143B2C454CEA")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ISample
{
   String Value
   {
      [return: MarshalAs(UnmanagedType.BStr)]
      get;
      [param: In, MarshalAs(UnmanagedType.BStr)]
      set;
   }

   void ShowValue();
}

class ManagedSample : ISample
{
   public String Value { get; set; }

   public int GetLength()
   {
      // Delphi wird mit hier mit "this" klarkommen, da es als ISample genutzt werden kann
      return DelphiImports.GetValueLength(this);
   }

   public void ShowValue()
   {
      Console.WriteLine("From .Net {0}", Value);
   }
}

static class DelphiImports
{
   [DllImport("SampleInterfaceDLL")]
   static extern void CreateSample([MarshalAs(UnmanagedType.Interface)]out ISample instance);

   public static ISample CreateSample()
   {
      ISample instance;
      CreateSample(out instance);
      return instance;
   }

   [DllImport("SampleInterfaceDLL")]
   public static extern int GetValueLength([MarshalAs(UnmanagedType.Interface)]ISample instance);
}

class Program
{
   static void Main(string[] args)
   {
      var delphiInstance = DelphiImports.CreateSample();

      delphiInstance.Value = "Test";
      var l1 = DelphiImports.GetValueLength(delphiInstance);

      var managedInstance = new ManagedSample { Value = "Def" };
      var l2 = managedInstance.GetLength();

      Array.ForEach(new[] { delphiInstance, managedInstance },
                    i => i.ShowValue());
   }
}
Hiermit könntest du sogar einen Parser in C# schreiben:
Code:
[ComVisible(true)]
[Guid("C9B334E4-BDAE-419E-9305-143B2C454CEA")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ISample
{
   String Value
   {
      [return: MarshalAs(UnmanagedType.BStr)]
      get;
      [param: In, MarshalAs(UnmanagedType.BStr)]
      set;
   }

   void ShowValue();
}

class ManagedPlugin : ISample
{
   public String Value { get; set; }

   public void ShowValue()
   {
      Console.WriteLine("From .Net {0}", Value);
   }
}

static class Exports
{
   [DllExport]
   static void CreateSample([MarshalAs(UnmanagedType.Interface)]out ISample instance)
   {
      instance = new ManagedPlugin { Value = "Managed Plugin!" };
   }

   [DllExport]
   public static int GetValueLength([MarshalAs(UnmanagedType.Interface)]ISample instance)
   {
      return (instance.Value ?? "").Length;
   }
}
[1]und das willst du weil platte C-kompatible DLLs bestenfalls als menschenverachtende Folter in Den Haag verhandelt werden sollten

Mithrandir 21. Dez 2009 11:05

Re: DLL Parser Plugins
 
Zitat:

Zitat von Elvis
[1]und das willst du weil platte C-kompatible DLLs bestenfalls als menschenverachtende Folter in Den Haag verhandelt werden sollten

Genau das hatte ich vor. Nun stolpere ich aber alle Nase lang über Interfaces und bekomme ein schlechtes Gewissen. :stupid: (Auch wenn ich die Idee mit einem generischen Pointer und einer einfach Konstante, damit die DLL weiß, was da für ein Typ hinter dem Pointer steckt, reizvoll finde.. :) ).

Ich raffe irgendwie den C#-Teil noch nicht so ganz. Nehmen wir mal folgendes Beispiel:

Das Programm soll modular aufgebaut sein. Das heißt, ich soll nach belieben Plugins hinzufügen und wegnehmen können. Nehmen wir mal an, dass das Programm eine Klasse hat, die so aufgebaut ist:

Delphi-Quellcode:
  Type
    Tst_mmclass = class
      private
        (* Path of the file being played *)
        fMediaFile : AnsiString;
        (* Handle of the current audio stream *)
        fCurrentStream : HSTREAM;
        (* Handle of the application *)
        fAppHandle : HWND;
        (* Stream is playing *)
        fStreamIsPlaying: Boolean;
        (* We need the Plugin Observer, so this class can adress plugins *)
        fPluginObserver: TPluginObserver;
        (* Assign Channel to new Media File *)
        procedure NewMediaFile(const Value: AnsiString);
        procedure SetPluginObserver(const Value: TPluginObserver);
      public
        property MediaFile      : AnsiString read fMediaFile    write NewMediaFile;
        property AppHandle      : HWND       read fAppHandle    write fAppHandle;
        property CurrentStream  : HSTREAM    read fCurrentStream write fCurrentStream;
        property StreamIsPlaying : Boolean   read fStreamIsPlaying write fStreamIsPlaying;
        property PluginObserver : TPluginObserver read fPluginObserver write SetPluginObserver;
        (* Playback Control *)
        procedure Play;
        procedure Pause;
        procedure NextTrack;
        procedure PrevTrack;
        (* Initialization of Bass.dll *)
        procedure InitBass(Path: AnsiString);
        (* Deinitialization of Bass.dll *)
        procedure DeInitBass;
        (* Con- & Destructor *)
        Constructor Create;
        Destructor Destroy; override;
    end;
Ferner gibt es eine Klasse, TPluginObserver, die eine Liste aller geladenen Plugins verwaltet. Außerdem soll sie eigentlich auch die Aufrufe der Plugins und die Nachrichten der Plugins an die Anwendung verwalten. (Ja, mit meinem System hätte ich mit SendMessage Application-interne Nachrichten verschickt, mit entsprechenden Pointer garniert.) Meine Hoffnung an Interfaces ist, dass ich das gar nicht machen muss.

Angenommen, ich möchte jetzt, dass ein Plugin eine Playlist bereitstellt. Wie würde jetzt ein Beispiel mit Interfaces aussehen, in dem das Plugin dem Hauptprogramm den Dateipfad übergibt (soll in die Property "MediaFile" geschrieben werden) und anschließend die Prozedur "Play" ausführt. Und wie würde man in die andere Richtung kommunizieren? Denn wenn der Anwender auf "Next Track" klickt, muss ich dem Plugin ja mitteilen können, dass ich jetzt den nächsten Eintrag aus der Liste brauche...

Oder sollte ich zur Kommunikation meine Observer-Klasse ausbauen?

Würde mich über ein Beispiel zu diesem Anwendungsfall freuen, ich stehe gerade etwas auf dem Schlauch... :gruebel:

MyRealName 21. Dez 2009 18:40

Re: DLL Parser Plugins
 
Schau Dir doch mal meine Modular Application Framework Components an, die sind für den Hausgebrauch und Freeware kostenlos. Die bieten ein plugin-interface, welches Du ohne code zu schreiben einbinden kannst und während der Laufzeit des programms neue plugins installieren oder de-installieren, code in DLLs aktivieren und vieles mehr.

Zu finden mit tutorials und einer grösseren Beispiel-Anwendung unter www.maf-components.com

Mithrandir 21. Dez 2009 20:30

Re: DLL Parser Plugins
 
Danke für das Angebot, aber du hast vermutlich die großen VCL/RTL-Units ala Classes und SysUtils drinne, oder? Außerdem handelt es sich um eine Open-Source App. ;)

MyRealName 21. Dez 2009 20:52

Re: DLL Parser Plugins
 
Wenn Du mit VCL/RTL arbeiten willst/musst, dann brauchst Du die wohl. ;)
Und leider kann ich opensource nicht mit meinem Source unterstützen, sonst verkauf ich ja nichts mehr und in 3 Wochen gibt es 3 chinesische/indische/pakistanische Anbieter von meinem System, hehe

Ansonsten lass VCL/RTL als dynamische Laufzeitbibliothek laufen, dann kann Dein System auf mehreren Delphi-Versionen übersetzt werden und die DLLs können sich klein halten. Spätestens wenn Du Formulare etc in DLLs auslagerst (Config-Dialoge für Plugins zum Bsp.) dann brauchst Du die eh dort und kannst/musst eine shared Version der VCL/RTL nutzen.

Mithrandir 21. Dez 2009 20:55

Re: DLL Parser Plugins
 
Zitat:

Zitat von MyRealName
Wenn Du mit VCL/RTL arbeiten willst/musst, dann brauchst Du die wohl. ;)

Da ich aber ohne die VCL arbeite (aka Non-VCL ;) ), stören mich die Units. Aber dennoch danke für dein Angebot. :)

Elvis 21. Dez 2009 22:21

Re: DLL Parser Plugins
 
Das ist gar nicht so schlimm.
Du musst allerdings ein bissel umdenken.
Du kannst du nicht diese blödsinnigen Methodpointer-Properties nehmen, die Delphi "Events" nennt,
Denn die haben ja immer nur einen Subscriber, wobei die Worte "Subscriber" oder "Event" bei der saubilligen Implementierung wie sie die VCL nutzt wohl maßlos übertrieben sind.
Da es keine interoperablen Multicast-Methodpointer gibt, musst du dir halt ein Interface bauen, was du wie einen Delegate nutzt.
Delphi-Quellcode:
type
  IEventHandler = interface
  ['']
     procedure Invoke; safecall;
  end;
Du kannst dir dann einen EventManager, Eventsink, Listener , Observer oder wie auch immer du es nennen magst, bauen, der solche IEventHandler in einer InterfaceList verwaltet und nach außen nur Add und Remove zur Verfügung stellt.
Das heißt, Plugins können nur einen Handler hinzufügen, oder exakt ihren wieder entfernen. (Sich also nicht in die Quere kommen)
Es gibt dann ein weiteres Interface, was von dem IEventManager ableitet, und ihm die Methoden Clear und Raise gibt.
Den einen um alle Handler loszuwerden, den anderen um alle zu feuern.
Dieses 2. Interface ist nur innerhalb der App zu benutzen.

Deine App könnte den Teil, der das Playback abbildet als einen Service zur Verfügung stellen:
Delphi-Quellcode:
IPlaybackEventHandler = interface
  procedure Invoke(aState : TPlaybackState); safecall; //halt irgendein enum
end;

IPlaybackEvent = interface
  procedure AddHandler(const aHandler : IPlaybackEventHandler); safecall;
  procedure RemoveHandler(const aHandler : IPlaybackEventHandler); safecall;
end;

IPlaybackProvider = interface
  procedure Play; safecall;
  procedure Stop; safecall;
  procedure Next; safecall;
  ...
  property StateChanges : IPlaybackEvent read ...; // der Manager
  property StateChanged : IPlaybackEvent read ...; // der Manager
end;
Ein Plugin könnte den Host (aus seiner Sicht: die App) nach dem Playback-Service erfragen und dort einen Handler reinwerfen, der es über Änderungen informiert.

Willst du deine App wirklich ernsthaft erweiterbar machen, dann solltest du auch innerhalb der App alles so lösen.
Dann merkst du wenn deine API, der Teil, den auch die Plugins nutzen können, nicht mächtig genug ist.

Es ist Blödsinn Dinge innerhalb der App anders zur Verfügung zu stellen, als für Plugins. (Warum darf die App direkt ins Menü pfuschen?)
Und direkten zugriff auf Dinge wie Controls oder Menus kannsu schonmal komplett vergessen, da du sonst keine Benachrichtigungen abfangen und in einem Plugin auswerten könntest, richtig?

Mithrandir 22. Dez 2009 10:01

Re: DLL Parser Plugins
 
Waaaah, ich raffs immer noch nicht... :wall: Ich habe noch nie (also, nicht direkt :stupid: ) selbst interfaces implementieren müssen. (Durchgearbeitet: Dit hier, dit und dit och. )

Also, janz langsam, damit ich das auch verstehe:
(ich wiederhole es quasi nochmal, mit ein paar Anmerkungen, wo ich was nicht verstanden habe...)

Ich komme weg von den Klassen mit ihren Methoden. (Klassen pöhse! :stupid: ) Ich brauch die Klassen nur noch, um die Interfaces implementieren zu können. Zuerst baue ich mir für meine benötigen Funktionen Interfaces. Jetzt kann ich das Kind ja bei Namen nennen: Es geht natürlich um SmallTune. Daher auch meine Abneigung gegenüber Closed Source, Sysutils, Classes usw...

Was kann der Audioplayer? Er kann Mediadateien wiedergeben (Playback), und er stellt ein TNA-Menü bereit (ContextMenu). Nach langem Überlegen beim Schreiben dieses Beitrags bin ich zu der Überzeugung gekommen, dass das die Grundfunktionen sind.
Es gibt dann ja auch noch ein "Display", welches der Player zum Anzeigen nutzt. Ich wüsste aber jetzt nicht, ob es gut wäre, die Klasse in ein Interface umzuwandeln, da ich zum Einen dran mit-, sie aber nicht selbst geschrieben habe, und zum Anderen vielleicht auch gar nicht möchte, das Plugins auf das Design zugreifen können...

Ich bräuchte also (mindestens) zwei EventHandler:

Delphi-Quellcode:
 
  (* Playback State *)
  TPlaybackState = ( stPlaying, stStopped, stNewTrack, stPreviousTrack, stNextTrack );

  IPlaybackEventHandler = interface
    ['{00000000-0000-0000-0000-000000000000}']
    procedure Invoke(SomeState: TPlaybackState);
  end;

  IPlaybackEvent = interface
    ['{00000000-0000-0000-0000-000000000001}']
    procedure AddEvent(const Ev: IPlaybackEventHandler);
    procedure DeleteEvent(const Ev: IPlaybackEventHandler);
  end;

  IPlaybackProvider = interface
    procedure Play; safecall;
    procedure Stop; safecall;
    procedure Next; safecall;
    {...}
    property StateChanges : IPlaybackEvent {read ...}; // der Manager
    property StateChanged : IPlaybackEvent {read ...}; // der Manager
  end;

  (* ContextMenu *)
  type
    TMenuItem = packed record
      ID : Cardinal;
      Caption : WideString;
    end;

  IContextMenu = interface
    (* Getter *)
    function GetMenuHandle: HMENU;
    (* Setter *)
    procedure SetMenuHandle(Value: HMENU );
    procedure AppendMenuItem(Itm : TMenuItem );
    procedure DeleteMenuItem(ItmID : Cardinal );
    property MenuHandle: HMENU read GetMenuHandle write SetMenuHandle;
  end;

  IContextMenuEventHandler = interface
    ['{00000000-0000-0000-0000-000000000002}']
    procedure Invoke({?}); //Event wird ausgelöst, wenn ein Item angeklickt wird.
  end;

  IContextMenuEvent = interface
    ['{00000000-0000-0000-0000-000000000003}']
    procedure AddEvent(const Ev: IContextMenuEventHandler);
    procedure DeleteEvent(const Ev: IContextMenuEventHandler);
  end;
Ein paar Verständnisfragen:

Angenommen, ich möchte jetzt das Menü erstellen. Wenn ich das richtig verstanden habe, darf ich das nicht in der Anwendung im Abschnitt WM_CREATE direkt tun, sondern sollte eine Eigenschaft der Klasse TContextMenu ( die ich von IContextMenu ableite ) nutzen, oder?

Alle Plugins, die entsprechende EventHandler für das ContextMenu registriert haben, sollen benachrichtigt werden, sobald ein Eintrag angeklickt wird. Ziehe ich das System so durch, muss die Anwendung selbst auch Events registrieren, oder? Denn Punkte wie "Schließen", "Info", "Hilfe" sollen ja nicht durch Plugins eingetragen werden, sondern durch die Anwendung.
Die Nachricht, dass ein Eintrag angeklickt wurde, bekommt ja immer das Parent des Menüs. Das wäre in diesem Fall meine Anwendung, also alles wie bisher. Die Anwendung würde dann alle WM_COMMAND-Nachrichten vom Typ WM_BUTTON an das IContextMenu weiterleiten, welches seinerseits ein Event an alle registrierten Plugins auslösen würde. Die müssten dann gucken, ob das Event für sie gedacht ist.

Damit alle Plugins angesprochen werden können, bastel ich mir einen EventManager. Hier melden sich alle Plugins an. Dafür müssen die Plugins von sich aus ein Interface bereitstellen, bspw. IPlugin:

Delphi-Quellcode:
  Type
    TPluginType = (ptPlayback, ptContextMenu (* usw? *) );

  IPlugin = interface
    ['{00000000-0000-0000-0000-000000000004}']
    (* Getter *)
    function GetPluginMajorVersion: Cardinal;
    function GetPluginMinorVersion: Cardinal;
    function GetName: WideString;
    function GetAuthor: WideString;
    function GetAuthorURL: WideString;
    function GetPluginType: WideString;

    property PluginMajorVersion : Cardinal read GetPluginMajorVersion;
    property PluginMinorVersion : Cardinal read GetPluginMinorVersion;
    property Name : WideString read GetName;
    property Author : WideString read GetAuthor;
    property AuthorURL : WideString read GetAuthorURL;
    property PluginType : TPluginType read GetPluginType;
  end;
Die Frage ist, wie bekomme ich es hin, eine Interface Liste aufzubauen, ohne die Classes.pas zu nutzen?
Die Plugins können ja jetzt daherkommen, und die Interfaces, die sie brauchen, implementieren. Und dann bräuchte ich ja auch noch so eine Art "Handshake", oder? Denn irgendwie muss ja bspw. auf die Instanz des Playback Services zugreifen, den die Anwendung erstellt hat, damit das Plugin "Play" aufrufen kann, oder?

Sorry, aber ich betrete gerade komplettes Neuland und fühl mich etwas unsicher dabei. Daher kommt das alles etwas "stackselig" daher. :)

//Edit: Oder mache ich mir das Leben gerade unnötig schwer? :gruebel:

Elvis 22. Dez 2009 10:55

Re: DLL Parser Plugins
 
Sorry, wenn ich kurz angebunden bin, aber wir müssen gleich los und einen Weinaxbaum holen. ;-)
Ich habe für das Menuzeugs letzlich ein Sample geschrieben, das liegt auf dem Firmenrechner, und auf den werde ich mich heute Abend wohl sowieso nochmal einklinken müssen.
Wie du Funktionalität den Plugins zur Verfügung stellst habe ich hier kurz angerissen.
Zur TInterfaceList, die macht ja keine Zauberei, das geht auch ohne Classes.pas. Wenn du die nämlich nicht nimmst, hast da ja sowieso sicherlich schon eine eigene Basisliste, auf der du die InterfaceList aufbauen könntest. Der Sinn davon ist, nur dass der Referenzzähler schon gepflegt wird, ohne dass du dir da ein Bein abbrechen musst.

Oh und eins noch: Records sind WERTE, keine Objekte und erst Recht keine Entitäten.
Du kannst nichts damit modellieren ohne auf die *piep* zu fliegen. Deshalb kann ein Record auch kein Menuitem sein.
Mühe dich mit dem Menu erstmal nicht ab, ich habe da ein schönes Beispiel (zumindest fast fertig), dass ich nur holen und polieren müsste.

Mithrandir 22. Dez 2009 10:58

Re: DLL Parser Plugins
 
Zitat:

Zitat von Elvis
Sorry, wenn ich kurz angebunden bin, aber wir müssen gleich los und einen Weinaxbaum holen. ;-)

Den hamma Gott sei dank schon. :)
Zitat:

Zitat von Elvis
Ich habe für das Menuzeugs letzlich ein Sample geschrieben, das liegt auf dem Firmenrechner, und auf den werde ich mich heute Abend wohl sowieso nochmal einklinken müssen.
Wie du Funktionalität den Plugins zur Verfügung stellst habe ich hier kurz angerissen.
Zur TInterfaceList, die macht ja keine Zauberei, das geht auch ohne Classes.pas. Wenn du die nämlich nicht nimmst, hast da ja sowieso sicherlich schon eine eigene Basisliste, auf der du die InterfaceList aufbauen könntest. Der Sinn davon ist, nur dass der Referenzzähler schon gepflegt wird, ohne dass du dir da ein Bein abbrechen musst.

Zitat:

Zitat von Elvis
Mühe dich mit dem Menu erstmal nicht ab, ich habe da ein schönes Beispiel (zumindest fast fertig), dass ich nur holen und polieren müsste.

Cool, danke... :firejump:

Mithrandir 23. Dez 2009 10:10

Re: DLL Parser Plugins
 
:stupid:

Ich möcht' ja nicht unhöflich, aufdringlich, verlangend, fordernd oder gar ausfallend wirken (vor allem, nachdem ich diesen Thread mittlerweile gekapert habe :mrgreen: ), aaaaaber:

Postest du das Beispiel noch vor den Feiertagen? Werde mir vermutlich bis Dienstag eine (Online-)Auszeit nehmen (müssen), da wäre es ganz schön, wenn man für die Zeit Spiel, Spaß und Spannung hätte. :mrgreen:

:stupid:

Elvis 23. Dez 2009 12:40

Re: DLL Parser Plugins
 
Zitat:

Zitat von Daniel G
Postest du das Beispiel noch vor den Feiertagen?

Mal schauen, wenn ich jetzt hier anfange groß rumzuprogradingsen, könnte das meinen Geschenkeertrag böse in Gefahr bringen. :mrgreen:
Aber ich schaue mal, ob ich es dazwischen schummeln kann. :zwinker:

Mithrandir 23. Dez 2009 12:59

Re: DLL Parser Plugins
 
Nur kein Stress... Rennt ja nich weg... :)

Ich nerv sonst nach den Feiertagen nochmal. :mrgreen:

Schöne Weihnachten. :xmas:

Mithrandir 29. Dez 2009 16:05

Re: DLL Parser Plugins
 
Elvis,

Matze meinte, es wäre in Ordnung, dich jetzt nochmal an diesen Thread zu erinnern. :mrgreen:

//Edit: Hmm, schade. Hätte eigentlich eine PN werden sollen. :mrgreen: :wall:


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:29 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