Anmelden

View Full Version : Eigene Character-Funktionen



Seiten : [1] 2 3

Kurmas Zeschlon
10-02-14, 16:05
Hallo zusammen,

nachdem ich zuletzt hier und da Probleme mit zu wenig dynamischem Speicher hatte -- ein Konzept, dass ich noch nicht richtig verstehe -- möchte ich hier mal fragen, wie ich am intelligentesten Funktionen/Prozeduren designe, die ähnlich wie die BIFs %Xlate, %ScanRpl etc. Charactervariablen manipulieren.

Bisher habe ich hierzu VARYING-Felder mit LEN(4000000) genutzt. Parameter jeweils mit CONST versehen.

Also:


P fURLEscape B EXPORT
D fURLEscape PI A LEN(4000000) VARYING
D Text A LEN(4000000) CONST VARYING

Ist es ratsam, so vorzugehen? Durch den Rückgabewert brauche ich ja mehr Speicher, als wenn ich nur einen per Referenz übergebenen Parameter hätte, oder? Es scheint Probleme zu geben, wenn ich viele solcher Funktionen in einem Programm benutze.

Wie machen das denn die BIFs? Denen kann man sehr große Felder übergeben und bekommt auch schöne Rückgabewerte. ohne dass ich bisher auch bei großen Feldern Probleme bekommen hätte. Kann man deren Verhalten simulieren?

Schöne Grüße

andreaspr@aon.at
10-02-14, 16:11
Hallo,
Für genau diese Situation gibt es in RPG ab 7.1 das Schlüsselwort RTNPARM bei der Procedurdefinition:

D getFileData pr a varying len(1000000)
D rtnparm
D file a const varying len(500)

/free
data = getFileData ('/home/mydir/myfile.txt');

B.Hauser
10-02-14, 16:33
... aber Vorsicht!
Der Aufruf mit Rückgabe-Wert funktioniert nur beim Aufruf aus RPG.
Beim Aufruf aus anderen Programmiersprachen muss der Rückgabe-Wert über den ersten Parameter abgehandelt werden.

Birgitta

Fuerchau
10-02-14, 16:59
Das Problem mit dem Speicher beginnt ja schon beim Übergabeparameter.
Wenn dieser CONST ist, legt der Compiler ja automatisch eine Kopie in der Größe an.
Aber ohne CONST kann ich keine dynamische Übergabe kodieren:
MyFunc(Var1);
MyFunc('Text');
Problematisch wirds dann noch bei Rekursion und geschachtelten Funktionen.
Bifs sind intern wohl etwas anders kodiert.

Dynamisch geht es eigentlich nur per Pointer.
Allerdings muss die Aufrufkonvention genau eingehalten werden.

Beschränke dich doch einfach auf max. 32K-Variablen, das reicht in 99,999% aller Fälle.

B.Hauser
10-02-14, 17:10
Bei VALUE wir immer eine Kopie erstellt.
Bei CONST nur dann, wenn die Parameter-Definition (Aufruf/Prototyp) abweichend ist. Es wird immer ein Pointer (entweder auf das Original-Feld oder die Kopie übergeben.

Birgitta

Fuerchau
10-02-14, 17:14
CONST erzwingt ebenso eine Kopie, damit die aufgerufene Funktion den Speicher nicht ändern kann.
Dies ist Sinn und Zweck von CONST.
VALUE arbeitet (fast) genauso, nur dass scalare Datentypen nicht kopiert werden sondern direkt im Stack abgelegt werden (CLLE-Problem).
Bei Zeichenvariablen wird der Inhalt kopiert und ein Pointer im Stack abgelegt.
Die Kopie benötigt dann halt den Platz.

BenderD
10-02-14, 17:35
P fURLEscape B EXPORT
D fURLEscape PI A LEN(4000000) VARYING
D Text A LEN(4000000) CONST VARYING
Es scheint Probleme zu geben, wenn ich viele solcher Funktionen in einem Programm benutze.


... was für Probleme? alles was lokal definiert ist, ist automatic storage, wird also zur Laufzeit für die Lebensdauer der Procedure allociert und wieder freigegeben. Addieren tut sich das allenfalls, wenn das geschachtelt ist. Die %bifs werden zur Compiletime aufgelöst, da kann man an der Länge noch fummeln, das geht mit eigenen Funktionen, die erst zur Bindezeit aufgelöst werden wohl nicht. Ein wenig simulieren könnte man das mit call by reference und Pointer Rückgabe, halte ich aber von der Lesbarkeit und Robustheit für Contraproduktiv.

D*B

@Baldur: das mit dem CONST scheint mir nicht so! CONST ist eigentlich nur hopefully CONST und wird zur Laufzeit nicht (in Worten: nicht!) sichergestellt.

Kurmas Zeschlon
11-02-14, 13:07
Vielen Dank an Euch alle!
Zunächst einmal: RTNPARM hat geholfen.

CONST VARYING habe ich verwendet, um größtmögliche Flexibilität beim Aufruf der Funktion zu haben, also Charactervariablen verschiedener Länge und auch Literale verwenden zu können.

Bei der XML-Verarbeitung bin ich zu 4000000-Feldern übergegangen, sobald es möglich war, sodass ich Dokumente jetzt immer in einem Rutsch verarbeiten kann. Für Characterfunktionen, die allgemein eingesetzt werden sollen, sind mir also 32KB zu wenig. Vielleicht war das nicht der schlaueste Ansatz, aber inzwischen nutzen einige Programme die 4Mio-Funktionen und es wäre ein Riesenaufwand, alles wieder zurückzubiegen.

Dazu kommt ein gewisses Chaos innerhalb meiner Serviceprogramme, das aus dem Learning-by-Doing-Ansatz unserer Abteilung entspringt. Mein Konzept ändert sich, je mehr ich dazulerne. Natürlich ist das einer stringenten Architektur nicht gerade förderlich.

Könnt Ihr mir vielleicht ein Buch oder eine Schulung empfehlen, die zum Thema hat, wie man organisiert eine "Bibliothek" von Prozeduren aufbaut, diese zentral zur Verfügung stellt und wie man diese am besten wartet?

Zurzeit verfolge ich den Ansatz eines Serviceprogramms für allgemeine Funktionen und daneben weitere, die Prozeduren für verschiedene mehr oder weniger abgeschlossene Bereiche enthalten (Web-Portal, Web-Schnittstellen usw.). Vor kurzem wollte ich eine Prozedur aus einem der speziellen Serviceprogramme in das allgemeine verschieben, was zu einer Neukompilierungsorgie sondergleichen geführt hat.

Sorry, jetzt bin ich wohl ziemlich vom Thema abgekommen. Soll ich besser einen neuen Thread aufmachen?

Fuerchau
11-02-14, 13:22
Auch dieses Thema wurde hier (mit unterschielichen Meinungen) schon mehrfach behandelt.
Das Neukompilieren ist nicht erforderlich, wenn man mit Bindarylanguage und eigenen Signaturen arbeitet.
Man legt
a) eine eigene Signatur fest
b) bestimmt genau die Reihenfolge der Exporte
Ohne Signatur rechnet das System an hand der Exporte immer eine eigene aus, so dass diese sich halt mit jedem neuen Export verändert, mit eigener Signatur gibts dieses Problem nicht.
Neue Export müssen immer am Ende angefügt werden!
Begründung:
Der Compiler merkt sich den Einsprungspunkt an hand der relativen Position in der Liste.
Verschiebt sich die Liste, wird ohne Signaturwechsel sogar die falsche Prozedur aufgerufen!

Ohne Bindarylanguage sortiert der Compiler (bzw. CRTSRVPGM) die Exporte alphabetisch und rechnet eine neue Signatur aus.
Dies führt dann eben zur Neucompilierungsarie damit es keine Runtimefehler gibt!

Empfehlenswert ist auch ein eigenes BNDDIR.

Wie du die Serviceprogramme organisierst bleibt letztlich dir überlassen.
Es macht aber durchaus Sinn, globale Funktionen und Business-Funktionen (nach Theman, Aufgaben)aufzuteilen.

BenderD
11-02-14, 13:30
... hier fängt doch genau der Unfug an!!! Mit dieser Strategie kann ich eine Procedure genau nicht verschieben, die lässt nämlich das Entfernen eines Exports nicht zu - dann geht der Punk ab!!!

Zunächst muss man erst mal die Anforderung festlegen:
- bin ich Software Haus und brauche ein modulares Deployment
- bin ich Anwender und will schnelle Ladezeiten
- will ich maximale Modularisierung und Flexibilität

BTW: neu kompilieren ist nicht erforderlich, neues binden der verwendenden Programme/SRVPGMs reicht.

D*B