Page 1 sur 3
Lancer une procedure enregistre en variable
Publié : sam. 24/juin/2017 20:49
par ChaudEf
Bonsoir
est il possible de faire un truc pareil?
Code : Tout sélectionner
procedure mafunc()
debug "ok"
endprocedure
a.s = "mafunc"
launchprocedure(a)
Merci beaucoup
Re: Lancer une procedure enregistre en variable
Publié : sam. 24/juin/2017 23:07
par Ollivier
Code : Tout sélectionner
;{
Macro Quote:"
EndMacro
Macro FuncDef(x):Func(UCase(Quote#x#Quote) ) = @x()
EndMacro
Global NewMap Func()
Macro FuncCall(Name, Arg1 =, Arg2 =)
CompilerIf Quote#Arg1#Quote = ""
CallFunctionFast(Func(UCase(Quote#Name#Quote) ) )
CompilerElse
CompilerIf Quote#Arg2#Quote = ""
CallFunctionFast(Func(UCase(Quote#Name#Quote) ), Arg1)
CompilerElse
CallFunctionFast(Func(UCase(Quote#Name#Quote) ), Arg1, Arg2)
CompilerEndIf
CompilerEndIf
EndMacro
;}
Procedure Test()
MessageRequester("", "")
EndProcedure
FuncDef(Test)
FuncCall("Test")
Note :
- c'est insensible à la casse donc pas de confusion possible
- Ici, c'est limité à 2 arguments facultatifs mais on peut augmenter le nombre d'arguments facultatifs si besoin
Re: Lancer une procedure enregistre en variable
Publié : dim. 25/juin/2017 0:46
par Ar-S
@ChaudEf
Comme tu l'as écrit non, ça ne veut pas dire grand chose ou il manque des éléments.
Ce que tu as écrit signifie
Code : Tout sélectionner
;Tu crées une procédure mafunc() qui debug un simple "ok"
procedure mafunc()
debug "ok"
endprocedure
; Tu crées une variable texte a.s qui se nomme "mafunc" mais elle n'a aucun rapport avec la proce mafunc() plus haute
a.s = "mafunc"
; Tu lances une procedure launchprocedure(a) qui n'existe pas... En supposant que le (a) représente le a.s plus haut, tu n'as pas le bon type.
launchprocedure(a)
Re: Lancer une procedure enregistre en variable
Publié : dim. 25/juin/2017 7:43
par Ollivier
On vire des guillemets en dernière ligne,
on envoie le bug en
bug report sur le forum officiel
http://www.purebasic.fr/english/viewtop ... =4&t=68686
Ça te plaît maintenant ?
Code : Tout sélectionner
;{
Macro Quote:"
EndMacro
Macro FuncDef(x)
Func(UCase(Quote#x#Quote) ) = @x()
EndMacro
Global NewMap Func()
Macro FuncCall(Name, Arg1 =, Arg2 =)
CompilerIf Quote#Arg1#Quote = ""
CallFunctionFast(Func(UCase(Quote#Name#Quote) ) )
CompilerElse
CompilerIf Quote#Arg2#Quote = ""
CallFunctionFast(Func(UCase(Quote#Name#Quote) ),
Arg1)
CompilerElse
CallFunctionFast(Func(UCase(Quote#Name#Quote) ),
Arg1, Arg2)
CompilerEndIf
CompilerEndIf
EndMacro
;}
Procedure Test()
MessageRequester("", "")
EndProcedure
FuncDef(Test)
FuncCall(Test)
Re: Lancer une procedure enregistre en variable
Publié : dim. 25/juin/2017 7:55
par Ollivier
Zut... Les guillemets c'était pas là qu'il fallait que je les saute... Corrigé.
@ChaudEf
C'est bon comme ça?
Code : Tout sélectionner
;{
Macro Quote:"
EndMacro
Macro FuncDef(x)
Func(UCase(Quote#x#Quote) ) = @x()
EndMacro
Global NewMap Func()
Macro FuncCall(Name, Arg1 =, Arg2 =)
CompilerIf Quote#Arg1#Quote = ""
CallFunctionFast(Func(UCase(Name) ) )
CompilerElse
CompilerIf Quote#Arg2#Quote = ""
CallFunctionFast(Func(UCase(Name) ),
Arg1)
CompilerElse
CallFunctionFast(Func(UCase(Name) ),
Arg1, Arg2)
CompilerEndIf
CompilerEndIf
EndMacro
;}
Procedure Test()
MessageRequester("", "")
EndProcedure
FuncDef(Test)
FuncCall("Test")
Re: Lancer une procedure enregistre en variable
Publié : dim. 25/juin/2017 8:08
par Zorro
ouaip, yen a qui code comme il parle !!!
on comprends rien !
voici ce que tu Peux faire :
il te faut une procedure qui sert de lanceur de procedure en fonction d'une chaine de caractere
ben voila comment faire :
Code : Tout sélectionner
Declare mafunc()
Declare lanceur_de_proc(a.s)
calldebugger
; on fourni le nom de la procedure1 qu'on veux lancer au lanceur de procedure
a.s = "mafunc1"
lanceur_de_proc(a.s)
; on fourni le nom de la procedure2 qu'on veux lancer au lanceur de procedure
a.s = "mafunc2"
lanceur_de_proc(a.s)
; Procedure 1 qui sera lancé par le lanceur de procedure
procedure mafunc1()
debug "ok1"
endprocedure
; Procedure 2 qui sera lancé par le lanceur de procedure
procedure mafunc2()
debug "ok2"
endprocedure
Procedure lanceur_de_proc(a.s)
; le lanceur de procedure ..
; il lance une procedure en fonction de la chaine de caractere qui sert ici de commande de lancement
Select a.s
Case "mafunc1"
mafunc1()
Case "mafunc2"
mafunc2()
EndSelect
EndProcedure
c'etait tout con hein ??

Re: Lancer une procedure enregistre en variable
Publié : dim. 25/juin/2017 9:58
par G-Rom
ChaudEf a écrit :Bonsoir
est il possible de faire un truc pareil?
Code : Tout sélectionner
procedure mafunc()
debug "ok"
endprocedure
a.s = "mafunc"
launchprocedure(a)
Merci beaucoup
Oui, cela s'appelle de la reflection, tu peu utilisé une Map & un pointeur pour cela , exemple tout simple :
Code : Tout sélectionner
Procedure foo()
Debug "foo"
EndProcedure
NewMap *FuncPtr()
*FuncPtr("foo") = @foo()
CallCFunctionFast(*FuncPtr("foo"))
Re: Lancer une procedure enregistre en variable
Publié : lun. 26/juin/2017 19:48
par Demivec
Code : Tout sélectionner
Prototype rProcedure_Params_0()
Runtime Procedure mafunc()
Debug "ok"
EndProcedure
Procedure launchprocedure(a.s)
Protected procName.rProcedure_Params_0 = GetRuntimeInteger(a + "()")
procName()
EndProcedure
a.s = "mafunc"
launchprocedure(a)
Re: Lancer une procedure enregistre en variable
Publié : lun. 26/juin/2017 20:34
par Ollivier
Demivec a écrit :Code : Tout sélectionner
Prototype rProcedure_Params_0()
Runtime Procedure mafunc()
Debug "ok"
EndProcedure
Procedure launchprocedure(a.s)
Protected procName.rProcedure_Params_0 = GetRuntimeInteger(a + "()")
procName()
EndProcedure
a.s = "mafunc"
launchprocedure(a)
J'avoue que ChaudEf n'exige pas d'avoir, à la volée, une liste des noms, de ses fonctions.
Dans ce cas, ta suggestion est très bien trouvée.
Et, dans le cas général, ça reste aussi un très bon exemple complet d'utilisation de la librairie native RunTime. Merci pour cette info.
Re: Lancer une procedure enregistre en variable
Publié : mar. 27/juin/2017 8:29
par Kwai chang caine
Alors là bravo DEMIVEC
Tous ces exemples sont super intéressants, mais alors le tiens est carrément époustouflant.
J'ai même cru que c'était pas du PB

Runtime...jamais entendu parler ...
Merci beaucoup pour ce code

Re: Lancer une procedure enregistre en variable
Publié : mar. 27/juin/2017 17:54
par JohnJohnsonSHERMAN
Merci Demivec !

J'avais déjà fait ca mais sans les prototypes, donc c'était plus sale... Je ne savais pas qu'on pouvait s'en servir dans ce cas
@KCC, c'est pas bien ca... T'as pas lu la Sainte Doc en entier??

Re: Lancer une procedure enregistre en variable
Publié : mer. 28/juin/2017 8:16
par Kwai chang caine
T'as raison, je lis déjà pas les doc d'aspirateur, alors une aussi grosse doc ...

C'est d'autant plus, "trop pas" (d'jeuns inside

) cool, car comme on le sait tous, il faut autant de temps pour faire une bonne doc que le programme lui même

J'espère que notre seigneur me pardonnera

Re: Lancer une procedure enregistre en variable
Publié : ven. 01/sept./2017 10:27
par Ormente
Bonjour les gens.
Je suis un petit nouveau ici : j'ai une License PB depuis des lustres mais n'avais quasiment jamais programmé avec. Je suis en train d'essayer un peu, et j'avais justement voulu faire le même genre de choses.
Voici ce à quoi j'étais arrivé :
(désolé j'ai l'habitude de commenter en langue des coins, mais si c'est un soucis je peux traduire)
Code : Tout sélectionner
OpenConsole()
#ITERS = 100000000
x = 12
y = 13
; Declare the signature of a function
Prototype.i bifunc(a.i, b.i)
; Function 1 compatible with the prototype
Procedure.i add(x.i, y.i)
ProcedureReturn x+y
EndProcedure
; Function 2 compatible with the prototype
Procedure.i mul(x.i, y.i)
ProcedureReturn x*y
EndProcedure
; the "trick" to test: function pointer call
; Does it work? YES!
*fun.bifunc = @add()
PrintN(Str(*fun(x,y)))
*fun.bifunc = @mul()
PrintN(Str(*fun(x,y)))
; Why the trick ? Because instead of repeating the same
; test in a loop i want To test beforehand and use the
; right procedure "directly". So instead of doing this:
PrintN("Loop with test:")
t = ElapsedMilliseconds()
For i = 1 To #ITERS
If x=12 : add(x,y) : Else : mul(x,y) : EndIf
Next
PrintN(Str(ElapsedMilliseconds() - t) + "ms")
; I would be doing this:
PrintN("Loop using the trick:")
t = ElapsedMilliseconds()
If x=12 : *fun = @add() : Else : *fun = @mul() : EndIf
For i = 1 To #ITERS
*fun(x,y)
Next
PrintN(Str(ElapsedMilliseconds() - t) + "ms")
; For the sake of comparison, the simple equivalent loop:
PrintN("Simple normal loop:")
t = ElapsedMilliseconds()
For i = 1 To #ITERS
add(x,y)
Next
PrintN(Str(ElapsedMilliseconds() - t) + "ms")
; Typical result (console exe, no debug, #ITERS = 100000000) :
;-------------------------------------------------------------
; Loop With test:
; 568ms
; Loop using the trick:
; 428ms
; Simple normal loop:
; 423ms
Re: Lancer une procedure enregistre en variable
Publié : ven. 01/sept./2017 10:51
par djes
Bienvenue Ormente !

C'est bien, tu débutes en PB mais tu sembles maîtriser les pointeurs ; je pense que tu vas facilement faire d'excellents codes !
Celui-ci est un excellent exemple, c'est très peu utilisé en BASIC, et pourtant comme tu l'as bien démontré, ça permet de gagner de la vitesse. C'est le genre de chose qui pourrait être prise en charge et repérée par l'éditeur/compilateur, en surlignant ces sortes de "surcharge d'opérateurs", et en renvoyant vers la définition. Ainsi on améliore le langage, mais on garde la lisibilité du BASIC.
Re: Lancer une procedure enregistre en variable
Publié : ven. 01/sept./2017 12:57
par JohnJohnsonSHERMAN
Bienvenue à toi Ormente
Exellente astuce ! Je n'y avais pas pensé, c'est trés pratique dans ces cas où plusieurs fonctions avec les mêmes prototypes doivent être choisies (if ou select), merci de l'astuce
<HS> Ca n'a rien à voir, mais suis-je le seul à rêver de surcharge d'opérateurs / de procédures en PB?

</HS>