Dynamisches Ausführen von Prozeduren

Konzeptionelles, Technisches, Termine, Fragen zum Hersteller usw.

Moderator: Moderatoren

Antworten
Benz
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 440
Registriert: Mo, 30. Mai 2011 15:06
Danksagung erhalten: 1 Mal

Dynamisches Ausführen von Prozeduren

Beitrag von Benz »

Hi,

Ich habe folgendes Problem:

Ich will Prozeduren dynamisch aufrufen, dabei habe ich hier z.B. den Prozeduraufruf:

Code: Alles auswählen

   oXBNN := "proc_versionsinfo(oDlg)"

         oXYZ:addItem( {"~"+VAR2CHAR(memindex)+Chr(9),;
             {|| &oXBNN },,;
                   XBPMENUBAR_MIA_OWNERDRAW },128;
              )
Jetzt kommt da allerdings die Fehlermeldung "Unknown Variable "ODLG" und als Zeile wird die letzte Zeile des hier angezeigten Codes angegeben. Wie kann ich einen Parameter in einem solchen Prozeduraufruf angeben, dass das trotzdem aufgerufen wird?

Die Variable oDlg ist definitiv vorhanden und auch mit einem Wert belegt an der Stelle, an der der Programmcode aufgerufen wird.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Dynamisches Ausführen von Prozeduren

Beitrag von Tom »

In Maktos verwendete Variablen müssen PRIVATE oder PUBLIC sein.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Dynamisches Ausführen von Prozeduren

Beitrag von brandelh »

Mach ein codeblock daraus und nutze eval für den Aufruf mit local variable
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Dynamisches Ausführen von Prozeduren

Beitrag von Tom »

Er macht das wahrscheinlich in einer Schleife.

Man könnte auch echte (nicht die Altmann'schen :wink: ) "detached locals" verwenden, aber wenn das Programm nicht gerade hochkritisch leistungsoptimiert ist, reicht es auch, "oDlg" als PRIVATE zu deklarieren, ohne diesen Code weiter ändern zu müssen.
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Dynamisches Ausführen von Prozeduren

Beitrag von AUGE_OHR »

ich sehe oDlg nur "im" String

Code: Alles auswählen

"proc_versionsinfo(oDlg)"
wenn oDlg ein Parameter sein soll so muss man das explizit übegeben, also "aufteilen"

"das" man den ganzen Codeblock in einer Function erstellen sollte ist klar.
die Frage von Benz ist wohl "wie" er ein Object in einen String bekommt ...
gruss by OHR
Jimmy
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Dynamisches Ausführen von Prozeduren

Beitrag von Tom »

Da ist kein Codeblock, nur ein Makro, das später in einem Codeblock ausgewertet wird. Und wenn man - laberfasel - "oDlg" vorher einfach als PRIVATE deklariert, funzt dieser Code. Ob er nun megatoll ist oder eher spaghettimäßig, ist doch letztlich nicht die Frage.
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Dynamisches Ausführen von Prozeduren

Beitrag von AUGE_OHR »

JA ... man "könnte" eine PUBLIC / PRIVATE verwenden ... :roll:
aber die Frage "an-und-für-sich" ist doch wie man ein Object in den Codeblock String von einem Makro bekommt :?:

ich hatte meine PUBLIC / PRIVATE mittels "Summer93" in Function umgewandelt.

Code: Alles auswählen

PROCEDURE MAIN
LOCAL oStatic,cb

   oStatic := XbpStatic():new(,,{0,0},{320,200}):create()
// statt PUBLIC - PRIVATE
   MyObj(oStatic)  	
   cb := MakeBock( "MyFunc","Hello world")
   EVAL(cb)
   WAIT
RETURN

FUNCTION MakeBock(cFunc,cString)
LOCAL bBlock
   bBlock := "{|| "+cFunc+"('"+cString+"')}"
RETURN &bBlock

FUNCTION MyFunc(cString)
LOCAL oObj := MyObj()
   oObj:SetCaption(cString)
RETURN NIL

FUNCTION MyObj(xValue)
STATIC oObj
   IF PCOUNT() > 0
      oObj := xValue
   ENDIF
RETURN oObj
da ich eine Menge PUBLIC / PRIVATE in meinem ehemaligen Cl*pper Code hatte habe ich alle Function in 1 x PRG gepackt und ein Array als STATIC verwendet. Der Zugriff erfolgt über #xtranslate (was den ehemaligen Variablen entspricht)

Code: Alles auswählen

#xtranslate cKDNR                => Stack\[SP,1]
#xtranslate cARTNR               => Stack\[SP,2]
...
#xtranslate lGetTimeout          => Stack\[SP,36]

STATIC Stack := {}
STATIC SP    := 0

FUNCTION _STACKINIT
   // Anzahl Elemente mit #xtranslate
   AADD( Stack, ARRAY( 36 ) )
   // n-Dim für MDI
   SP ++

   cKDNR          := SPACE(5)
   cARTNR         := SPACE(5)
...
   lGetTimeout    := .F.
   lGetTimeout    := 0

RETURN (SP)

FUNCTION _STACKEXIT(nThread)
LOCAL iMax

   ADEL(Stack,nThread)
   DO WHILE .T.
      iMax := LEN(Stack)
      IF iMax = 0
         EXIT
      ELSEIF Stack[iMax] = NIL
         ASIZE(Stack,LEN(Stack) - 1)
      ELSE
         EXIT
      ENDIF
   ENDDO
   SP := LEN(Stack)

RETURN (SP)
wie man sieht ist das Array n-Dim d.h. man kann damit auch MDI.
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Dynamisches Ausführen von Prozeduren

Beitrag von brandelh »

Warum so umständlich ?

Wenn oDLG der Standarddialog ist, könnte man den Parameter weg lassen und eine local mit SetAppWindow() füttern.

Wenn man die Funktion direkt schreiben könnte würde das ja so gehen:

Code: Alles auswählen

oPushButton:activate( {|| proc_versionsinfo(oDlg) } ) // detached local kann man bei so erstellten Codeblocks nutzen.
Wenn man sie zusammen setzen muss, geht das so:

Code: Alles auswählen

cCodeBlock := "{|o| proc_versionsinfo(o) }" // so kann man o übergeben ( |o| ) und intern auch verwenden ...
bCodeBlock := &(cCodeBlock )  // codeblock erzeugen
Eval( bCodeBlock, oDlg ) // hier kann man die local oDlg übergeben, die intern dann die o wird.
Natürlich hat Tom Recht, dass ein private auch gehen würde, aber wer weiß schon welche Nebenwirkungen dann wieder auftreten ;-)
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Dynamisches Ausführen von Prozeduren

Beitrag von Tom »

Benz will vermutlich dynamisch ein Menüsystem aufbauen, und er braucht das Objekt, das das Hauptfenster der Applikation hält, in den aufgerufenen Funktionen, wozu auch immer. Wenn "oDlg" nicht in irgendeiner aufgerufenen Funktion recycelt wird, ist es unproblematisch, die Objektvariable einfach als PRIVATE zu deklarieren (wenn die Funktionen allerdings nicht in eigenen Threads laufen, ist das Objekt in diesem Moment als Parameter überflüssig, weil sowieso in den aufgerufenen Funktionen sichtbar wäre). Auch das Laufzeitverhalten dürfte sich nicht im messbaren Bereich zu den anderen Lösungen unterscheiden. Eine "Gefahr" besteht beim Verwenden von PRIVATEs ansonsten nicht in dem Sinn, dass sie irgendwie instabil oder sonstwie gering verlässlich wären. Man muss eben nur aufpassen, dass die Wiederverwendung des Variablennamens für PRIVATEs oder PUBLICs in untergeordneten Variablen nicht erfolgt, weil sonst der Originalinhalt verloren oder beschädigt werden kann. Und man sollte mit Funktionalitäten wie SAVE TO vorsichtig sein, wenn sie so etwas betreffen könnten. Aber wer macht schon ein "SAVE TO ALL LIKE *"?
Herzlich,
Tom
Antworten