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

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

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

Message 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
Dernière modification par Ollivier le mer. 29/août/2007 19:18, modifié 2 fois.
MorpheusDX
Messages : 36
Inscription : mar. 21/août/2007 17:31

Message 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...)
Force et sagesse...
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message 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)
MorpheusDX
Messages : 36
Inscription : mar. 21/août/2007 17:31

Message 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
Force et sagesse...
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message 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!
gnozal
Messages : 832
Inscription : mar. 07/déc./2004 17:35
Localisation : France
Contact :

Message 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
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message 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
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message 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?
gnozal
Messages : 832
Inscription : mar. 07/déc./2004 17:35
Localisation : France
Contact :

Message 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().
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message 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
gnozal
Messages : 832
Inscription : mar. 07/déc./2004 17:35
Localisation : France
Contact :

Message 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.
MorpheusDX
Messages : 36
Inscription : mar. 21/août/2007 17:31

Message 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é...
Force et sagesse...
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ha ! ok !! :oops: :lol:
Répondre