Page 1 sur 1

CallFunctionFast:Retourner "Mémé kiffe les orties"

Publié : lun. 27/août/2007 18:46
par Ollivier
Dans le petit code qui suit, j'ai quelque chose de tordu dans la procédure Mux().
Est-ce que quelqu'un a une réponse sur le fait que 'Coucou!' arrive à s'afficher ?

Code : Tout sélectionner

Declare.S Fonction()
Declare.S Mux()

Global *Fonc = @Fonction()
Debug Mux()
End

Procedure.S Fonction()
  String.S = "Coucou!"
  ProcedureReturn String
EndProcedure

Procedure.S Mux()
  x.L = CallFunctionFast(*Fonc)
  String.S
  ProcedureReturn String.S
EndProcedure

Publié : lun. 27/août/2007 19:12
par MorpheusDX
Une histoire de pile je pense. En appelant la fonction Fonc par la fonction
CallFunctionFast, tu ne doit pas avoir de retour standart de ta fonction, et
ton 'Coucou' doit rester coincé sur le sommet de la pile.

D'ailleurs, si tu ecris cela:

Code : Tout sélectionner

Declare.S Fonction()
Declare.S Mux()

Global *Fonc = @Fonction()

Debug Mux()
End

Procedure.S Fonction()
  String.S = "Coucou!"
  ProcedureReturn String
EndProcedure

Procedure.S Mux()
  CallFunctionFast(*Fonc)
  String.S = "Encore"
 ProcedureReturn String.S
EndProcedure
tu obtiens 'Coucou!Encore'

Aux spécialistes de dire si c'est bien une amorce de réponse. :?:
(étrange quand même...)

Publié : lun. 27/août/2007 20:45
par Ollivier
Je ne sais pas si c'est aussi la pile, mais il y a autre chose. Et le souci c'est que ça crashe dès que j'ajoute un paramètre dans la procédure appelée par CallFast malgré le respect du nombre de paramètres.

M'étant pris le crâne avec la copie de chaîne dans une structure, j'ai appris que l'action de copie d'une chaîne vers une autre...

Code : Tout sélectionner

ChaineDestination.S = ChaineSource.S
...se fait en 2 étapes:

Code : Tout sélectionner

1 (Copie) ChaineResiduelle.S + ChaineSource.S
2 (Allocation mémoire et attribution) Attribution du nom 'ChaineDestination' au pointeur de la 'ChaineResiduelle'
En passant, un nom, après compilation est une adresse (pointeur).

Ce serait la raison pour laquelle 'Encore' s'ajoute à 'Coucou!' : Un retour de procédure appelée par CallFast() est une copie de chaîne avortée (étape 1 sans l'étape).

Mais ce qui m'exaspère encore plus, ce sont ces 3 codes qui diffèrent de peu pour pouvoir récupérer une chaîne:
>> Les 1ers et 2nd codes ne fonctionnent pas correctement
>> Le 3ème code qui 'injecte' une chaîne non nulle (même si c'est "haricot", "zoby one", etc...) fonctionne 8O
(C'est un peu tordu pour échanger des chaînes avec des fonctions DLLs)

Code : Tout sélectionner

Declare.L Fonction(c.L)             ; << Entrée LONG, Sortie LONG
Declare.S Mux() 

Global *Fonc = @Fonction() 

Debug Mux()
Debug "RIEN!!!"
End 

Procedure.L Fonction(c.L)           ; << Idem
  String.S = "Coucou!"
  *Ptr = @String
  ProcedureReturn *Ptr
EndProcedure 

Procedure.S Mux()
  *Ptr = CallFunctionFast(*Fonc, 0)  ; << Injection d'un LONG nul
  String.S = ""
  Repeat
    Ch.L = PeekB(*Ptr)
    If Ch = 0: Break: EndIf
    Debug Chr(Ch)
    *Ptr + 1
  ForEver   
 ProcedureReturn String.S 
EndProcedure

Code : Tout sélectionner

Declare.L Fonction(c.S)             ; << Entrée STRING, Sortie LONG
Declare.S Mux() 

Global *Fonc = @Fonction() 

Debug Mux()
Debug "Ci-dessus, une fausse chaîne (<> 'Coucou!')"
End 

Procedure.L Fonction(c.S)           ; << Idem
  String.S = "Coucou!"
  *Ptr = @String
  ProcedureReturn *Ptr
EndProcedure 

Procedure.S Mux()
  *Ptr = CallFunctionFast(*Fonc, "")  ; << Injection d'un STRING nul
  String.S = ""
  Repeat
    Ch.L = PeekB(*Ptr)
    If Ch = 0: Break: EndIf
    Debug Chr(Ch)
    *Ptr + 1
  ForEver   
 ProcedureReturn String.S 
EndProcedure

Code : Tout sélectionner

Declare.L Fonction(c.S)             ; << Entrée STRING, Sortie LONG
Declare.S Mux() 

Global *Fonc = @Fonction() 

Debug Mux()
Debug "Ci-dessus, ma chaîne est enfin trouvée ! ! !"
End 

Procedure.L Fonction(c.S)           ; << Idem
  String.S = "Coucou!"
  *Ptr = @String
  ProcedureReturn *Ptr
EndProcedure 

Procedure.S Mux()
  *Ptr = CallFunctionFast(*Fonc, "Au pifomètre")  ; << Injection d'un STRING non nul
  String.S = ""
  Repeat
    Ch.L = PeekB(*Ptr)
    If Ch = 0: Break: EndIf
    Debug Chr(Ch)
    *Ptr + 1
  ForEver   
 ProcedureReturn String.S 
EndProcedure
PS: Le code n°2 a quand même réussi à me donner le pointeur du titre d'une autre application dans la barre des tâches... (En semaine, je ne bois pas)

Publié : mar. 28/août/2007 6:45
par MorpheusDX
Je viens de regarder ton premier des 3 codes. En fait, je pense que ton soucis
vient du fait que tu réference un pointeur d'une variable locale, qui est détruite
dès que tu est sortie de ta procedure. Donc il est normal que le pointeur renvoyé
pointe sur une zone mémoire qui ne correspond plus a ta string.

si tu ecris cela:

Code : Tout sélectionner

Declare.L Fonction(c.L)             ; << Entrée LONG, Sortie LONG
Declare.S Mux()

Global  String.S = "Coucou!"
Global *Fonc = @Fonction()

Debug Mux()
Debug "T'A QUELQUES CHOSES"
End

Procedure.L Fonction(c.L)           ; << Idem
  ;String.S = "Coucou!"
  *Ptr = @String
  ProcedureReturn *Ptr
EndProcedure

Procedure.S Mux()
  *Ptr = CallFunctionFast(*Fonc, 0)  ; << Injection d'un LONG nul
  String2.S = ""
  Repeat
    Ch.L = PeekB(*Ptr)
    If Ch = 0: Break: EndIf
    Debug Chr(Ch)
    *Ptr + 1
  ForEver   
 ProcedureReturn String2.S
EndProcedure
cela fonctionne...
je pense qu'avec PB c'est comme tous les langages, toutes variable locale ne
vie que durant l'exe de la procedure, dès que tu en sort, elle est kill...

meme chose avec le code 2:

Code : Tout sélectionner

Declare.L Fonction(c.S)             ; << Entrée STRING, Sortie LONG
Declare.S Mux()

Global *Fonc = @Fonction()
Global String.S = "Coucou!"

Debug Mux()
Debug "Ci-dessus, une fausse chaîne (<> 'Coucou!')"
End

Procedure.L Fonction(c.S)           ; << Idem
  *Ptr = @String
  ProcedureReturn *Ptr
EndProcedure

Procedure.S Mux()
  *Ptr = CallFunctionFast(*Fonc, "")  ; << Injection d'un STRING nul
  String2.S = ""
  Repeat
    Ch.L = PeekB(*Ptr)
    If Ch = 0: Break: EndIf
    Debug Chr(Ch)
    *Ptr + 1
  ForEver   
 ProcedureReturn String2.S
EndProcedure

Publié : mar. 28/août/2007 20:31
par Ollivier
Ce que je souhaiterais comprendre c'est pourquoi "au pifomètre", "Cendrillon" ou "Mémé kiffe les orties" mis en paramètre fonctionne alors que "" (chaîne vide) ne fonctionne pas!

Publié : mer. 29/août/2007 14:05
par gnozal

Code : Tout sélectionner

Declare.s Fonction() 
Declare.s Mux() 

Prototype.s ProtoFonction()

Global FastFonction.ProtoFonction = @Fonction()

Debug Mux() 
End 

Procedure.s Fonction() 
  Protected String.s
  String = "Mémé kiffe les orties" 
  ProcedureReturn String 
EndProcedure 

Procedure.s Mux() 
  Protected String.s
  String = FastFonction()
  ProcedureReturn String
EndProcedure
ou

Code : Tout sélectionner

Declare.s Fonction() 
Declare.s Mux() 

Global *Fonc = @Fonction() 
Debug Mux() 
End 

Procedure.s Fonction() 
  Protected String.s
  String = "Mémé kiffe les orties" 
  ProcedureReturn String 
EndProcedure 

Procedure.s Mux() 
  Protected *StringPointer.String
  If *Fonc
    *StringPointer = CallFunctionFast(*Fonc) 
  EndIf
  If *StringPointer
    ProcedureReturn ""
  Else
    ProcedureReturn *StringPointer\s
  EndIf
EndProcedure
ou

Code : Tout sélectionner

Declare.s Fonction() 
Declare.s Mux() 

Global *Fonc = @Fonction() 
Debug Mux() 
End 

Procedure.s Fonction() 
  Protected String.s
  String = "Mémé kiffe les orties" 
  ProcedureReturn String 
EndProcedure 

Procedure.s Mux() 
  Protected *StringPointer
  If *Fonc
    *StringPointer = CallFunctionFast(*Fonc) 
  EndIf
  If *StringPointer
    ProcedureReturn ""
  Else
    ProcedureReturn PeekS(*StringPointer)
  EndIf
EndProcedure

Publié : mer. 29/août/2007 16:41
par Ollivier
...Et dans la bonne humeur et la joie de savoir que Mémé kiffait éperdument les orties, le puissant Gnozal fît apparaître les 3 chemins qui mènent aux strings...

@MorpheusDX : merci d'avoir mis la main au clavier.

@Gnozal : Je fais tomber le chapeau. C'est tout le nécessaire, rien que le nécessaire :D

Publié : mer. 29/août/2007 21:03
par Ollivier
Par contre, je ne comprends pas bien un des termes de cette ligne :

Protected *StringPointer.String

C'est la structure interne d'une chaîne?

Publié : jeu. 30/août/2007 7:51
par gnozal
La structure STRING est définie par défaut dans PB :

Code : Tout sélectionner

Structure STRING
  s.s
EndStructure
C'est une astuce qui permet de définir un pointeur vers une chaîne.
Dans le même ordre d'idées, il existe aussi les structures BYTE, LONG, etc... (tous les types supportés par PB)

Code : Tout sélectionner

a.s = "abcde"
*caractere.character = @a
While *caractere\c
  Debug *caractere\c
  Debug Chr(*caractere\c)
  *caractere + 1
Wend
çà évite les Peek()/Poke().

Publié : jeu. 30/août/2007 8:24
par Backup
gnozal a écrit :La structure STRING est définie par défaut dans PB :

Code : Tout sélectionner

Structure STRING
  s.s
EndStructure
C'est une astuce qui permet de définir un pointeur vers une chaîne.
Dans le même ordre d'idées, il existe aussi les structures BYTE, LONG, etc... (tous les types supportés par PB)

Code : Tout sélectionner

a.s = "abcde"
*caractere.character = @a
While *caractere\c
  Debug *caractere\c
  Debug Chr(*caractere\c)
  *caractere + 1
Wend
çà évite les Peek()/Poke().

ok ! :) mais d'ou sort ut le \c

puisqu'aparement il n'y a que s.s dans la structure 8O

Publié : jeu. 30/août/2007 8:58
par gnozal
Dobro a écrit :ok ! :) mais d'ou sort ut le \c

puisqu'aparement il n'y a que s.s dans la structure 8O
Là, c'est un exemple avec la structure Character, qui permet d'analyser une chaîne caractère par caractère directement en mémoire.

Publié : jeu. 30/août/2007 9:04
par MorpheusDX
au meme titre qu'il existe une structure au sein de PB

Code : Tout sélectionner

Structure STRING
   s.s
EndStructure
il existe aussi une structure

Code : Tout sélectionner

Structure character
  c.c
EndStructure
d'ou les *caractere\c par la suite.

[EDIT] double post désolé...

Publié : jeu. 30/août/2007 10:00
par Backup
ha ! ok !! :oops: :lol: