Einzelnen Beitrag anzeigen

Andre1

Registriert seit: 19. Nov 2016
8 Beiträge
 
#1

Dynamischer Methoden Aufruf mit Record Referenzen

  Alt 19. Jun 2022, 19:09
Hallo,

ich habe eine Wrapper Bibliothek erstellt, mit der man aus der Programmiersprache D auf Firemonkey zugreifen kann [1].
Ein einfaches Beispiel in D sieht dann so aus:

Code:
import delta.core;
import System.Classes, System.UITypes, FMX.Forms, FMX.Types, FMX.Memo;

void main()
{
    deltaLibrary.load(`.\views\Win32\Debug\Project1.dll`);
   
    Application.Initialize;
    Application.MainForm = TCustomForm.CreateNew(Application);
    Application.MainForm.Caption = "Sample";
   
    auto memo = TMemo.Create(Application.MainForm);
    memo.Lines.Add("Hello World!");
    memo.Align = TAlignLayout.Client;
    memo.Parent = Application.MainForm;
   
    Application.MainForm.Show();
    Application.Run();
}
Die Project1.dll ist in Delphi geschrieben und bietet Funktionen um dynamisch Delphi Class Instances anzulegen und deren
Methoden aufzurufen. Das funktioniert soweit gut. Wo ich gerade nicht weiterkomme, ist wenn eine Methode ein Record Argument
hat.

Beispiel TCanvas.DrawLine hat zweimal den Record Type TPointF:

procedure DrawLine(const APt1, APt2: TPointF; const AOpacity: Single); overload;
In meiner DLL habe ich eine generische Funktion, um Instance Methoden aufzurufen, die als Argumente (Record, Record, Single)
erwarten:

Delphi-Quellcode:
procedure executeInstanceMethodReturnNoneArgsStructStructFloat(const Reference: Integer;
  const AName: PAnsiChar; Reference2, Reference3: Integer; s: Single); stdcall;
begin
    // Was muss ich hier machen?
    executeInstanceMethod(Reference, string(AName), [???]);
end;

function executeInstanceMethod(const Reference: Integer; const AName: string;
  const Args: array of TValue): TValue;
var
  context: TRttiContext;
  instType: TRttiInstanceType;
  obj: TObject;
begin
  context := TRttiContext.Create;
  try
    try
      obj := TObject(Reference);
      instType := (context.GetType(obj.ClassType) as TRttiInstanceType);
      result := instType.GetMethod(AName).Invoke(obj, Args);
    except
      on E: Exception do
        writeln(E.ClassName + ' error raised, with message : ' + E.Message);
    end;
  finally
    context.Free;
  end;
end;
(Das Argument Reference hat die Klassen Referenz zu TCanvas, AName beinhaltet den Methoden Namen DrawLine, danach kommen die eigentlichen
Argument für die DrawLine Methode)

Aus meinem Programm möchte ich dann beim Aufruf von
"executeInstanceMethodReturnNoneArgsStructStructFl oat" Referenzen auf Records (D Strukturen die binär kompatibel sind) übergeben.

In der Funktion "executeInstanceMethodReturnNoneArgsStructStructFl oat" sollen dann diese Record Referenzen umgewandelt
werden, in etwas mit der dann am Ende die TRttiMethod.Invoke Methode etwas anfangen kann.

Ist das technisch überhaupt machbar und wenn es gehen sollte, wie könnte das Coding dafür ungefähr aussehen?

Viele Grüße
André

[1] https://github.com/andre2007/delta-fmx-10-2-1
  Mit Zitat antworten Zitat