PascalScript unter ARM(RPI) Funktionen hinzufügen

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
dsn1980
Beiträge: 3
Registriert: Do 19. Dez 2013, 22:14

PascalScript unter ARM(RPI) Funktionen hinzufügen

Beitrag von dsn1980 »

Hallo,

Ich schreibe gerade ein Programm welches unter dem Raspberry Pi laufen soll jedoch scheitere ich daran unter PascalScript mittels AddFunktion eine Funktion zu übergeben.
Gleiches Problem besteht auch darin mittels AddMethod eine Prozedur oder Funktion zu übergeben. Diesen Umstand habe ich bis gestern auch so akzeptiert und mir mittels einer zusätzlichen Globalen Klasse dann die Variablen auch geholt. Das Klappte wunderbar unter Windows/Delphi und Windows/Lazarus(Intel). Ohne Probleme wurde der Source auch von Lazarus unter dem RPI kompiliert jedoch beim ausführen des Testscripts brach er dann auch hier immer wieder ab wenn eine Funktion aufgerufen wurde. Habe mittels Debugger dann gemerkt das er "Müll" an die Funktion übergibt und desshalb aussteigt. Selbst dan der hinzugefügten Funktion Now und Format scheitert es.

Es gibt eine Basisklasse TScriptEngine, diese erzeugt für jedes Script vor dem Starten eine "Instanz" in der alle Daten für das Script drin sind. Dies nutze ich um die Variablen aus den RS232 Modulen zu bekommen und um dort SQL Queries abzulegen.
Wie gesagt es ist sehr einfach gehalten vom Ablauf her.

Das hier ist die original Funktion:

Code: Alles auswählen

function PS_GetDevice(const S: string): string;
var
  ScriptEngineObjs: TScriptEngineObjs;
  Index: Integer;
begin
  WriteLn('PROC::GetDevice::ENTER');
  WriteLn('PROC::GetDevice::Instanz=' + S); // Absturz bzw. der Thread beendet sich. In S stehen nicht sichtbare Zeichen. Sollte aber sein 12356456456_Script3.pas
  if ScriptEngine.FindInstance(S, Index) then
  begin
    WriteLn('PROC::GetDevice::Instance found');
    ScriptEngineObjs := ScriptEngine.GetInstance(Index);
    Result := ScriptEngineObjs.Device;
  end
  else
    WriteLn('PROC::GetDevice::Instance not found');
  WriteLn('PROC::GetDevice::END');
end;


Baue ich die Funktion in eine Prozedur um dann läuft sie anstandslos

Code: Alles auswählen

procedure PS_GetDevice2(Instance: string; var ADevice: string);
var
  ScriptEngineObjs: TScriptEngineObjs;
  Index: Integer;
begin
  WriteLn('PROC::GetDevice::ENTER');
  WriteLn('PROC::GetDevice::Instanz=' + Instance);
  if ScriptEngine.FindInstance(Instance, Index) then
  begin
    WriteLn('PROC::GetDevice::Instance found');
    ScriptEngineObjs := ScriptEngine.GetInstance(Index);
    ADevice := ScriptEngineObjs.Device;
  end
  else
    WriteLn('PROC::GetDevice::Instance not found');
  WriteLn('PROC::GetDevice::END');
end;


Meine OnCompile sah so aus

Code: Alles auswählen

procedure TScriptEngineThread.PSCompile(Sender: TPSScript);
begin
  Sender.AddFunction(@PS_WriteLn, 'procedure WriteLn(const S: string);');
  Sender.AddFunction(@PS_GetDevice, 'function GetDevice(const S: string): string;')// Fehler
  //Sender.AddFunction(@PS_GetDevice2, 'procedure GetDevice(Instance: string; var ADevice: string);'); // läuft
  Sender.AddFunction(@PS_GetModul, 'function GetModul(Instance: string): string;');
  Sender.AddFunction(@PS_GetParam, 'function GetParam(Instance: string): string;');
  Sender.AddFunction(@PS_GetData, 'function GetData(Instance: string): string;');
  Sender.AddFunction(@PS_WriteToModul, 'procedure WriteToModul(Device: string; Modul: string; Param: string; Data: string);');
  // SQL Communication
  Sender.AddFunction(@PS_QueryAdd, 'function QueryAdd(Instance, Name: string): Boolean);');
  Sender.AddFunction(@PS_QueryRem, 'function QueryRem(Instance, Name: string): Boolean);');
  Sender.AddFunction(@PS_Query, 'procedure Query(Instance, Name: string; SQL: string);');
  Sender.AddFunction(@PS_QueryRecordCount, 'function QueryRecordCount(Instance, Name: string): Integer;');
  Sender.AddFunction(@PS_QueryRowsAffected, 'function QueryRowsAffected(Instance, Name: string): Integer;');
  Sender.AddFunction(@PS_QueryFirst, 'procedure QueryFirst(Instance, Name: string);');
  Sender.AddFunction(@PS_QueryLast, 'procedure QueryLast(Instance, Name: string);');
  Sender.AddFunction(@PS_QueryNext, 'procedure QueryNext(Instance, Name: string);');
  Sender.AddFunction(@PS_QueryPrior, 'procedure QueryPrior(Instance, Name: string);');
  Sender.AddFunction(@PS_QueryEof, 'function QueryEof(Instance, Name: string): Boolean;');
  Sender.AddFunction(@PS_QueryReadAsInt, 'function QueryReadAsInt(Instance, Name: string; Fieldname: string): Integer;');
  Sender.AddFunction(@PS_QueryReadAsStr, 'function QueryReadAsStr(Instance, Name: string; Fieldname: string): string;');
  Sender.AddFunction(@PS_QueryReadAsFloat, 'function QueryReadAsFloat(Instance, Name: string; Fieldname: string): Double;');
  Sender.AddFunction(@PS_QueryReadAsBoolean, 'function QueryReadAsFloat(Instance, Name: string; Fieldname: string): Boolean;');
//  Sender.AddFunction(@PS_GetDBData, 'function DBData(Device: string; Modul: string; Param: string): string;');
 
  Sender.AddFunction(@Format, 'function Format(const Format: string; const Args: array of const): string;');
  Sender.AddFunction(@Sleep, 'procedure Sleep(milliseconds: Cardinal);');
  Sender.AddFunction(@PS_DateTimeToStr, 'function DateTimeToStr(const DateTime: Double): string;');
  Sender.AddFunction(@PS_Now, 'function Now: Double;');
end;


Standard Funktionen wie StrToInt/IntToStr laufen dagegen. diese sind ja schon im PascalScript enthalten. Es sollte also auch möglich sein diese so zu übergeben, denke ich zumindest.

Ich nutze:
Raspbian
Lazarus/FP v1.2.4+dfsg2-1
PascalScript auch die aktuellste von Git

Kennt jemand bereits dieses Problem und konnte es lösen?
Bin für jede Hilfe dankbar.

MfG
Daniel

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: PascalScript unter ARM(RPI) Funktionen hinzufügen

Beitrag von theo »

Wo hast du gelesen, dass das auf ARM läuft?
Hier steht sogar, dass es nur auf 32bit intel läuft.
http://wiki.freepascal.org/Pascal_Script
K.A. ob das noch aktuell ist.

dsn1980
Beiträge: 3
Registriert: Do 19. Dez 2013, 22:14

Re: PascalScript unter ARM(RPI) Funktionen hinzufügen

Beitrag von dsn1980 »

Wenn ich mir die entsprechenden .inc Dateien(arm.inc) ansehe lässt es vermuten das es unter ARM läuft, zumindest zu gewissen Teilen.
Dazu kommt ja wie bereits geschrieben das es pauschal ja bereits läuft und Funktionen die intern von PS hinzugefügt werden ebenfalls.

edit: Schreibfehler korrigiert.
Zuletzt geändert von dsn1980 am Mi 25. Mär 2015, 21:57, insgesamt 1-mal geändert.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: PascalScript unter ARM(RPI) Funktionen hinzufügen

Beitrag von theo »

Ja, stimmt. Das könnte laufen.
Ich kann dir aber nichts zu deinem Problem sagen.
Vllt. weiß Chrisitan was.

martin_frb
Beiträge: 572
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: PascalScript unter ARM(RPI) Funktionen hinzufügen

Beitrag von martin_frb »

Geht es um Funktionen (nicht OO) oder Methoden (Foo.Bar)?


Funktionen lassen sich auf 2 Wege einbinden, siehe:
components\macroscript\emscriptclasses.pas
DEFINE PasMacroNoNativeCalls

Allerdings, keine Ahnung ob es da docs gibt....


Was Methoden (OO) betrifft, der Lazarus Code (1.4 hat eine fast aktuelle Version) hat in der ARM include, Code fuer "self". Ich kann allerdings nicht selbst testen....

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: PascalScript unter ARM(RPI) Funktionen hinzufügen

Beitrag von Christian »

Nein, ich bin noch nicht weiter als das meine Scriptengine sich aufm Raspi übersetzen lässt. Mir ist derzeit imapserver,caldav,carddavserver aufm Raspi wichtiger als das scripting. Werd aber evntl auch noch darüber stolpern. Leider legt der Hauptentwickler nicht sehr viel Wert auf Freepascal und andere Plattformen als von Delphi unterstützt.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

dsn1980
Beiträge: 3
Registriert: Do 19. Dez 2013, 22:14

Re: PascalScript unter ARM(RPI) Funktionen hinzufügen

Beitrag von dsn1980 »

Es geht um beides. Wobei der Umstand das ich "Self" nicht nutzen kann nicht so schlimm ist. wie bereits geschrieben habe ich mir da etwas drumherum gebaut.
Jedes Script läuft in einem eigenen Thread mit FreeOnTerminate. Wenn ich ein Script ausführe wird in einer Liste erzeugt in der alle Variablen die von außen kommen abgelegt. Diese sind dann über einen Timestamp mit Suffix abrufbar.
Dieser Schlüssel wird dem Script als Konstante eingefügt. Danach habe ich alle Befehle die auf Variablen und Objekte zugreifen erweitert um den Schlüssel. Ist der Thread abgelaufen wird diese Instanz wieder freigegeben.
Klar nicht sehr schön aber es läuft nun zuverlässig. Schade ist nur das ich alle Funktionen so umbauen musste das ich den eigentlichen Rückgabewert nun als var/out in die Prozedur einbauen musste. Bei dem geringen Befehlssatz den diese Script Engine aber nutzt ist das so noch vollkommen in Ordnung, nur schade eben.
Was ich nicht geschaft habe war NOW, Format und DateTimeToStr. Aber diese Funktionen sollten mir nur am Amfang helfen Fehler zu finden. Im Normalbetrieb werden auch diese nicht genutzt.

Da ich die Script Engine aber noch gerne weiter ausbauen würde und ggf. für andere Projekte nutzt möchte(auf ARM) wäre es natürlich auch sehr schön wenn ich diesen Umweg jetzt nur für dieses Projekt gehen müsste.
die macroscriptclasses habe ich mir zwar angesehen steige da aber nicht so recht durch und die arm.inc ist Identisch mit dem Repository.

Wäre also weiter offen für Hinweise wie man dieses Problem unter ARM in den Griff bekommt.

martin_frb
Beiträge: 572
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: PascalScript unter ARM(RPI) Funktionen hinzufügen

Beitrag von martin_frb »

Also bei mir

Code: Alles auswählen

 
*** B:/laz_other/Extensions/PascalScript/PascalScript/Source/arm.inc   Sun Jan 04 13:47:03 2015
--- B:/lazarus_latest/components/PascalScript/Source/arm.inc   Wed Nov 05 10:00:42 2014
***************
*** 206,215 ****
--- 206,219 ----
      then begin
        case res.atype.basetype of
          btStaticArray, btRecord: addgen(dword(res.dta));
        end;
      end;
+
+   if assigned(_Self) then begin
+     addgen(dword(_Self));
+   end;
 
    { process all parameters }
    for i := 0 to Params.Count-1 do begin
      if Params[i] = nil
        then Exit;
 


Und fuer NOE-OO Funktionen:
"AExec.RegisterDelphiFunction" fuehrt den asm code in arm.inc aus. Und da liegt das Problem.

"AExec.RegisterFunctionName" umgeht das. (siehe components\macroscript\emscriptclasses.pas)
Man muss dann allerdings die parameter aus der "TPSStack" structure auslesen.

Antworten