Ceci est un pis-aller.
Je suis toujours à la recherche d’une possibilité de :
1) passer des structures complexes en entrée et en sortie d’une procédure.
2) Permettre d’imbriquer les procédures sous forme de fonction explicite u=f(x,y,z)
Voir à ce sujet http://www.purebasic.fr/french/viewtopi ... 5&p=118993
Il est actuellement impossible de passer des structures par valeur >8 octets avec des $00 .On peut par contre passer des structures par adresse.
Imaginons donc une fonction explicite de type *u=f(*x,*y) avec *.. comme pointeur.
Si l’on ne prend aucune précaution *u à toujours la même adresse.
L’exemple suivant est un cas d’école car on peut réaliser l’addition directement mais pour la simplicité de l’exemple j’ai pris l’addition de deux nombres type .d passés en structure en entrée et en sortie.
Code : Tout sélectionner
Procedure.l add_d(*v1.double,*v2.double)
Static res0.d,NewMap stoc.double()
; Protected res0.d ;; ATTENTION cette option ne fonctionne pas pour une sortie procedurereturn car la zone est reinitialisée à chaque appel .et la valeur contenue à l’adresse est perdue sitôt hors du sous/prg
res0.d=*v1\d+*v2\d
AD_CLF=@res0
ProcedureReturn AD_CLF
EndProcedure
Gosub subr1
End
subr1:
Debug "********************************* Commence avec une nouvelle protection des variables internes au sous/prg *******************"
vA1.d=38.00
vA2.d=48.00
Debug "******* les adresses et les valeurs *res *res1 *res2 sont différentes elles ne sont écrasées que par la volonté du programmeur *******"
Debug "******* pour chacun des 3 appels de add_d() *res *res1 *res2 les adresses et les valeurs *res *res1 *res2 restent identiques *******"
*res.double=add_d(@va1,@va2)
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" ="+StrD(*res\d)+" adresse="+Hex(*res)+ " *res "
vA2+1.00
*res1.double=add_d(@va1,@va2)
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" ="+StrD(*res1\d)+" adresse="+Hex(*res1)+" *res1 "
Debug "*res\d="+StrD(*res\d)+" adresse="+Hex(*res)+" *res "
vA1+1.00
*res2.double=add_d(@va1,@va2)
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" ="+StrD(*res2\d)+" adresse="+Hex(*res2)+" *res2 "
Debug "*res\d="+StrD(*res\d)+" adresse="+Hex(*res)+" *res "
Debug "*res1\d="+StrD(*res1\d)+" adresse="+Hex(*res1)+" *res1 "
Debug "************* essai d'imbrication des procédures pour vérifier le résultat **********"
va3.d=200.23
*res3.double=add_d(@Va1,add_d(@vA2,@va3))
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" + Va3="+StrD(va3)+" ="+StrD(*res3\d)+" adresse="+Hex(*res3)+" *res3 add_d() imbriquée"
Debug "*res\d="+StrD(*res\d)+" adresse="+Hex(*res)+" *res "
Debug "*res1\d="+StrD(*res1\d)+" adresse="+Hex(*res1)+" *res1 "
Debug "*res2\d="+StrD(*res2\d)+" adresse="+Hex(*res2)+" *res2 "
VA1+1.01
vA2+1.02
VA3+1.03
*res4.double=add_d(@Va1,add_d(@vA2,@va3))
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" + Va3="+StrD(va3)+" ="+StrD(*res4\d)+" adresse="+Hex(*res4)+" *res4 add_d() imbriquée"
Debug "*res\d="+StrD(*res\d)+" adresse="+Hex(*res)+" *res "
Debug "*res1\d="+StrD(*res1\d)+" adresse="+Hex(*res1)+" *res1 "
Debug "*res2\d="+StrD(*res2\d)+" adresse="+Hex(*res2)+" *res2 "
Debug "*res3\d="+StrD(*res3\d)+" adresse="+Hex(*res3)+" *res3 "
Return
Pour pallier cet inconvénient j’ai ajouté une routine de stockage en MAP dans le sous/prg.
Code : Tout sélectionner
Procedure.l add_d(*v1.double,*v2.double,flag=1)
Static res0.d,NewMap stoc.double()
; Protected res0.d
;********************************************************** Placer ici la fonction à réaliser ************************************
res0.d=*v1\d+*v2\d
;*********************************************************** fin de la fonction à réaliser *********************************
; ******************************* contrôle et zone de stockage dans la map *******************************************************
If flag
; clef.s=StrD(*v1\d)+"+"+StrD(*v2\d) ; si la zone est plus complexe on peut convertir en HEXA ou en SHA1 MD5 CRC32 ect..
; exemple avec crc32
clef.s=Str(CRC32Fingerprint(*v1,8))+"+"+Str(CRC32Fingerprint(*v2,8)); le signe "+" pour différencier l'opérateur ici addition
AD_CLF.l=FindMapElement(stoc(),clef)
If AD_CLF.l<>0
; Debug "******** c<>0 ********"
resutm.d=stoc(clef)\d
If res0<>resutm
MessageRequester("Collision ", "Collision avec resultats différents res0="+StrD(res0)+" resutm="+StrD(resutm))
EndIf
Else
; Debug "********* nouvelle entrée adresse ********"
AD_CLF=AddMapElement(stoc(),clef)
stoc(clef)\d=res0
EndIf
Else
ad_clf=@res0
EndIf
ProcedureReturn AD_CLF
EndProcedure
Gosub subr1
Debug "**** le résultat est assez claire avec l'option STATIC associée à l'option MAP permet de consever l'adresse et la valeur ******"
Debug "**** on peut aussi imbriquer les appels de procédure comme les instructions PB ******"
End
; **** Les options SHARED et GLOBAL doivent avoir les mêmes noms entre le sous/prg et PRG principal donc manque de souplesse
subr1:
Debug "********************************* Commence avec une nouvelle protection des variables internes au sous/prg *******************"
vA1.d=38.00
vA2.d=48.00
Debug "******* les adresses et les valeurs *res *res1 *res2 sont différentes elles ne sont écrasées que par la volontè du programmeur *******"
Debug "******* pour chacun des 3 appels de add_d() *res *res1 *res2 les adresses et les valeurs *res *res1 *res2 restent identiques *******"
*res.double=add_d(@va1,@va2)
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" ="+StrD(*res\d)+" adresse="+Hex(*res)+ " *res "
vA2+1.00
*res1.double=add_d(@va1,@va2)
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" ="+StrD(*res1\d)+" adresse="+Hex(*res1)+" *res1 "
Debug "*res\d="+StrD(*res\d)+" adresse="+Hex(*res)+" *res "
vA1+1.00
*res2.double=add_d(@va1,@va2)
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" ="+StrD(*res2\d)+" adresse="+Hex(*res2)+" *res2 "
Debug "*res\d="+StrD(*res\d)+" adresse="+Hex(*res)+" *res "
Debug "*res1\d="+StrD(*res1\d)+" adresse="+Hex(*res1)+" *res1 "
Debug "************* essai d'imbrication des procédures pour vérifier le résultat **********"
va3.d=200.23
*res3.double=add_d(@Va1,add_d(@vA2,@va3))
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" + Va3="+StrD(va3)+" ="+StrD(*res3\d)+" adresse="+Hex(*res3)+" *res3 add_d() imbriquée"
Debug "*res\d="+StrD(*res\d)+" adresse="+Hex(*res)+" *res "
Debug "*res1\d="+StrD(*res1\d)+" adresse="+Hex(*res1)+" *res1 "
Debug "*res2\d="+StrD(*res2\d)+" adresse="+Hex(*res2)+" *res2 "
VA1+1.01
vA2+1.02
VA3+1.03
*res4.double=add_d(@Va1,add_d(@vA2,@va3))
Debug "Va1="+StrD(va1,2)+" + Va2="+StrD(va2)+" + Va3="+StrD(va3)+" ="+StrD(*res4\d)+" adresse="+Hex(*res4)+" *res4 add_d() imbriquée"
Debug "*res\d="+StrD(*res\d)+" adresse="+Hex(*res)+" *res "
Debug "*res1\d="+StrD(*res1\d)+" adresse="+Hex(*res1)+" *res1 "
Debug "*res2\d="+StrD(*res2\d)+" adresse="+Hex(*res2)+" *res2 "
Debug "*res3\d="+StrD(*res3\d)+" adresse="+Hex(*res3)+" *res3 "
Return
On peut maintenant, avec cette possibilité, réaliser des procédures explicites avec des structures complexes en entrée et en sortie. Elles seront de type :*u=f(*x,*y,) avec *.. comme pointeur. Elles conservent les résultats précédents et elles permettent l’imbrication *u=f(*x,f(*y,*z)). avec des structures de formes identiques en entrée et en sortie.
En attendant la possibilité de passer des structures complexes par valeurs qui seront certainement plus rapides et plus fiables que cette méthode.
A+