Board index CandiSoft Load! [GER] Unser Pluginsystem DLL-Erzeugung ohne Delphi

DLL-Erzeugung ohne Delphi

Ihr habt Fragen zum Pluginsystem? Wir beantworten sie gerne!

Post 31 May 2015 21:42

Posts: 9
Hi,

ich habe ein Plugin in Delphi (2010) geschrieben und bei der Programmierung gemerkt, dass es extrem aufwändig ist einfache Funktionen bzw deren Dokus zu finden (verglichen mit Java, C, Python usw)...
Einige die fehlten, waren schon in "Tools" implementiert aber trotzdem würde ich lieber Plugins in PureBasic schreiben.
Nun komme ich auch zur Frage: Da auf eurer Seite steht, man benötige Kenntnisse in einer Sprache, welche DLL-Erzeugung unterstüzt würde ich gerne wissen, wie eine solche Vorlage aussieht in einer anderen Sprache, wie PureBasic... Muss ich dafür die kompletten Dateien von den Beispielen portieren und dann die Funktionen genauso nennen? Könnte vllt. jmd ein Minimalbeispiel für eine DLL liefern, die equivalent in Delphi und in C oder noch besser in PureBasic ist?

Und btw. wenn ich die DLL kompiliert habe, wie kann ich die testen? Einfach in den Ordner zu packen scheint nicht zu funktionieren...

Post 02 Jun 2015 13:15
Hendi User avatar
CandiSoft Developer

Posts: 382
Grundsätzlich musst du zusehen, dass du die richtigen Methoden exportierst und entsprechend die Interfaces aus LoadInterface.pas portierst. LoadPlugin.pas musst du auch mehr oder weniger portieren, da jede Plugininstanz z.B. CreateList unterstützen muss (wird vom Hauptprogramm für GetFileInfoMulti gebraucht). Was letztendlich bei dir für eine Implementierung hinter ICSList steckt ist egal, so lange die 3 Methoden das tun, was sie sollen (die eine property ist nur syntaktischer Zucker und im Prinzip ein Alias für GetItem).

Die DLL muss 3 Funktionen exportieren:
CreateInstance, gibt ILoadPlugin zurück (genauer gesagt sollte es aber eines der drei Interfaces sein, die davon aberben, also IDecryptPlugin/IDownloadPlugin/IDownloadPlugin2).
GetCapabilities gibt die TCapabilities Struktur zurück, die Angaben darüber macht, was das Plugin kann (z.B. maximale Anzahlen an Chunks etc.).
GetHostFilter gibt einen ShortString zurück, mit dem festgestellt wird was für Links das Plugin bekommen soll (im einfachsten Fall z.B. 'uploaded.net/')

Ein größeres Problem könnte es für dich werden, Typkompatibilität herzustellen. Ich hab von PureBasic vorher noch nie gehört und weiß nicht wie sehr man da auf Low-Level Geschichten zugreifen kann.
Alle Methoden nutzen die stdcall-Aufrufskonvention - das ist dieselbe wie auch bei allen Windows APIs, da dürftest du also keine Probleme bekommen.

Zu den Typen kann ich dir nur sagen wie groß sie sind und was für Wertebereiche sie abdecken, wie du das in PureBasic umsetzt musst du leider selber austüfteln.
ShortString (nur in GetHostFilter verwendet): Statischer 256 Byte Puffer, wobei das erste Byte die Länge angibt und die restlichen 255 der eigentliche String sind.
WideString: Von Windows verwalteter String, entspricht BSTR.
Byte: 1 Byte, unsigned (0 ~ 255).
ShortInt: 1 Byte, signed (-128 ~ 127).
Integer: 4 Bytes, signed (−2.147.483.648 ~ 2.147.483.647).
Boolean: 1 Byte. 0 = False; 1 = True.
Enums (TStatusIndex/TLinkStatus): 1 Byte, der ordinale Wert des ersten Elements ist 0 usw.

Das hier könnte dir im Hinblick auf Interfaces und WideStrings helfen:
http://www.rsbasic.de/backupprogramme/COMTutorial.pdf
Der Teil über Variants ist für unsere Zwecke irrelevant.

Damit Load! dein Plugin lädt, muss es Versionsinformationen besitzen, d.h. mindestens irgendeine Version wie 1.0.0.0 und als Description den Pluginnamen, optimalerweise auch noch Copyright für die Autorspalte. In Delphi kannst du das in den Projekteinstellungen ändern.
Generell wird erstmal jede DLL aus dem Plugin Ordner geladen. Dann wird als erstes die Adresse von CreateInstance ermittelt und es aufgerufen. Auf dem zurückgegebenen Interface wird dann QueryInterface mit den GUIDs von IDownloadPlugin, IDownloadPlugin2 und IDecryptPlugin aufgerufen um zu gucken um was für ein Plugin es sich handelt. Wenn ich das richtig sehe sollte es aber selbst dann schon im About Dialog auftauchen, wenn CreateInstance erstmal nil/NULL zurückgibt (solange es halt mindestens Versionsinfos hat).

Post 02 Jun 2015 18:29

Posts: 9
Ich danke dir für die ausführliche Info, wenn ich demnächst Zeit habe versuche ich da ein Template zu portieren (habe allerdings bisher garkeine Erfahrung mit DLL)

Nach Einfügen der Version und Beschreibung geht das Plugin nun auch wie erwartet.

Post 13 Nov 2015 10:35
codermeister31 10% Load!er

Posts: 13
1nch0 wrote:
Ich danke dir für die ausführliche Info, wenn ich demnächst Zeit habe versuche ich da ein Template zu portieren (habe allerdings bisher garkeine Erfahrung mit DLL)

Schon Zeit gehabt? Allgemein reicht es schon den vorhandenen Quellcode vom Plugin zu veröffentlichen für andere interessierte Pluginentwickler. Grundsätzlich kann man fast jede Sprache nutzen um eine solche DLL zu bauen. PureBasic wäre mal interessant als Alternative weil es seltener eingesetzt wird.

Post 17 Dec 2015 18:14

Posts: 9
codermeister31 wrote:
Schon Zeit gehabt? Allgemein reicht es schon den vorhandenen Quellcode vom Plugin zu veröffentlichen für andere interessierte Pluginentwickler. Grundsätzlich kann man fast jede Sprache nutzen um eine solche DLL zu bauen. PureBasic wäre mal interessant als Alternative weil es seltener eingesetzt wird.


Du kannst hier Beispielcode herunterladen, man muss dann für eine ähnliche Seite nur wenige Zeilen anpassen.

Ich habe heute mal den oben genannten Code in Lazarus importiert und nach ca. 2 Stunden ändern geht es jetzt also der Code kompiliert eine DLL von Lazarus (Free-Pascal). Das Problem ist, dass ein Plugin nun ~220 statt ~50kb groß ist. Ich habe gelesen, dass es auch davon kommt wenn man ganze Module importiert, das habe ich bei Sleep() gemacht (SysUtils). Ich sehe auch keine Änderungen im Code, die wurden von Lazarus aus temporär wohl gemacht.

Daher meine Frage: Kann sich einer von euch das kurz angucken und ein Lazarus-Äquivalent auf eurer Seite ebenfalls hochladen, in dem kein unnützer Code drin ist? Dann können von nun an alle Leute Addons entwickeln, da Free-Pascal opensource ist und fast vollständig Delphi übersetzt.

Folgende Änderungen habe ich gemacht:
- {$mode delphi} überall oben, und die vorhandenen raus.
-
//function PosEx(const SubStr, S: String; Offset: Integer = 1): Integer;

Function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer;

var
  i,MaxLen, SubLen : SizeInt;
  SubFirst: Char;
  pc : pchar;
begin
  PosEx:=0;
  SubLen := Length(SubStr);
  if (SubLen > 0) and (Offset > 0) and (Offset <= Cardinal(Length(S))) then
   begin
    MaxLen := Length(S)- SubLen;
    SubFirst := SubStr[1];
    i := indexbyte(S[Offset],Length(S) - Offset + 1, Byte(SubFirst));
    while (i >= 0) and ((i + sizeint(Offset) - 1) <= MaxLen) do
    begin
      pc := @S[i+SizeInt(Offset)];
      //we know now that pc^ = SubFirst, because indexbyte returned a value > -1
      if (CompareByte(Substr[1],pc^,SubLen) = 0) then
      begin
        PosEx := i + SizeInt(Offset);
        Exit;
      end;
      //point Offset to next char in S
      Offset := sizeuint(i) + Offset + 1;
      i := indexbyte(S[Offset],Length(S) - Offset + 1, Byte(SubFirst));
    end;
  end;
end;   
// Cardinal noch prüfen??? Quelle strutils.pp aus Free-Pascal


- Dann die Sleep() auskommentiert und das komplette SysUtils geladen, hier reicht wohl auch Sleep aus Free-Pascal zu kopieren.
- In Tools: TListMethod = reference to function(Item: string): string; zu TListMethod = function(Item: string): string of object; // Stimmt das??

Einige Warnungen kommen noch die mMn auch zu warnen sind.

Wäre nice wenn das jmd mal hochlädt so wie es euer Meinung nach gut ist; das wäre dann endlich ein Anfang...


Return to Unser Pluginsystem

cron