Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Alternative zu Array of Const? (https://www.delphipraxis.net/144757-alternative-zu-array-const.html)

Leanahtan 15. Dez 2009 23:10


Alternative zu Array of Const?
 
Ich habe folgendes Problem. Per Event wird die Methode TMission.CallEvent(ProcName: String; Params: Array of const) aufgerufen. In CallEvent wird dann die Funktion mit dem Namen ProcName aufgerufen. Alle nötigen Parameter befinden sich in Params. Das ganze funktioniert zwar, hat aber einen Schönheitsfehler - es ist nicht möglich, als Parameter einen Record zu übergeben. Gibt es irgendwie eine Alternative, wie man einen Parameter-Array so definieren kann, dass er neben den Standardtypen auch Records aufnehmen kann? Das ganze sollte beim Aufruf möglichst trotzdem noch in der Form [Parameter1,Parameter2...] funktionieren.

Zusätzlicher Hintergrund: Das Ganze wird für eine ScriptEngine auf Basis von PascalScript benutzt. Dort gibt es bereits den Typ PPSVariant. TMission.CallEvent hat hauptsächlich die Aufgabe, die Übergebenen Parameter in eine PPSVariant-Variable zu schreiben. Ideal wäre natürlich eine Lösung, die gleich eine direkte Zuweisung an PPSVariant erlaubt, aber ich hoffe, dass ich die bei Bedarf auch selber gebastelt bekäme, daher ist dieser Punkt nicht ganz so wichtig. Hier trotzdem mal noch die entsprechende Hilfsfunktion:

Delphi-Quellcode:
function script_utils_constArrayToPSList(RunTime: TPSExec;Proc: TPSInternalProcRec;Params: Array of const): TPSList;
var
  s   : String;
  res : String;
  i   : Integer;
  ct  : PIFTypeRec;
  pvar : PPSVariant;
  Va  : Variant;
begin
  result:=TPSList.Create;

  s := Proc.ExportDecl;
  res := grfw(s);
  i := High(Params);
  while s <> '' do
  begin
    if i < 0 then
      raise Exception.Create('Not enough parameters');
    ct := RunTime.GetTypeNo(StrToInt(copy(GRLW(s), 2, MaxInt)));
    if ct = nil then
      raise Exception.Create('Invalid Parameter');
    pvar := CreateHeapVariant(ct);
    result.Add(pvar);

    with Params[I] do
    begin
      Va:=Unassigned;
      case VType of
        vtInteger:   Va := VInteger;
        vtBoolean:   Va := VBoolean;
        vtChar:      Va := VChar;
        vtExtended:  Va := VExtended^;
        vtString:    Va := VString^;
        vtAnsiString: Va := string(VAnsiString);
        vtCurrency:  Va := VCurrency^;
        vtVariant:   Va := VVariant^;
        vtObject:
        begin
          if ct.BaseType<>btClass then
            raise Exception.Create('Invalid Parameter');

          PPSVariantClass(pVar).Data:=VObject;
        end;
        else
          raise Exception.Create('Not supported Type');
      end;
    end;

    if not VarIsEmpty(Va) then
    begin
      if not VariantToPIFVariant(RunTime, Va, pvar) then
        raise Exception.Create('Invalid Parameter');
    end;

    Dec(i);
  end;
  if I > -1 then raise Exception.Create('Too many parameters');
  if res <> '-1' then
  begin
    pvar := CreateHeapVariant(RunTime.GetTypeNo(StrToInt(res)));
    result.Add(pvar);
  end;
end;

Stevie 16. Dez 2009 05:48

Re: Alternative zu Array of Const?
 
Entweder du nimmst anstatt eines Records eine Klasse und übergibst dann das Objekt, oder du definierst einen Pointer auf deinen Record und übergibst diesen. Bei beiden müsstest du die Signatur der von CallEvent aufgerufenen Methoden ändern.

Leanahtan 16. Dez 2009 11:29

Re: Alternative zu Array of Const?
 
Von Records zu Objekten zu wechseln, hätte einiges für sich - leider ist es in PascalScript aber nicht möglich, eigene Objekte zu erstellen. Den Umweg mit einem Pointer könnte man schon machen (und haben wir auch schon verwendet), allerdings ist das zum einen umständlich, zum anderen fehleranfällig.

Das eigentliche Problem ist, dass es ja nicht um vorgefertigte Skripte geht. Wir benutzen die Skriptengine, um damit 'Moddern' eigene AI-Skripte und Storyereignisse etc. zu ermöglichen. Die sind aber in der Regel nicht so erfahren im Umgang mit Delphi bzw. PascalScript. Leider ist es uns auch noch nicht gelungen, den Fehler schon beim Compilieren der Skripte mit einer Aussagekräftigen Meldung abzufangen - es kommt dann erst im Spiel zum Typemissmatch. Und da kann die Fehlersuche schonmal schwierig werden. Könnte man nicht TVarRec irgendwie erweitern?

himitsu 16. Dez 2009 11:37

Re: Alternative zu Array of Const?
 
Man kann eigene Variants erstellen, in Form von Objekten, welche dann über den Typ Variant verfügbar wären.

Witzig ist aber auch, daß man (seit D2006 besonders einfach) Interfaces in einen record einbinden und so mit Operatoren versehen oder eben Records fast wie Objekte verwenden kann. (abgesehn von den Vererbungssachen und dem Speichermanagerment)

Leanahtan 17. Dez 2009 19:54

Re: Alternative zu Array of Const?
 
Und wie genau soll mir das bei meinem Problem helfen? Es ist ja schön, wenn man in Delphi eigene Variant-Typen erzeugen kann, aber wenn ein Skripter einen einfachen Recordtyp in seinem Skript anlegt, und diesen dann als Parameter an den Array of Const übergibt, kommt es trotzdem zum Typemissmatch.
Oder könnte ich dann auf meinem eigenen Variant-Typ einen Array of MyVariant verwenden, der dann ebenfalls einen Aufruf per [...] ermöglicht? :wiejetzt:


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