Bonjour,
Suis assez en retard par rapport au sujet et d'accord avec Denis + remarque de Djes....
J'ai repris
le code de Denis ci-dessous avec des commentaires et debug pour chaque phase des pointeurs...
Cela rend les choses plus explicites !
Code : Tout sélectionner
; ***********************************************************
; POINTEURS : ?????
; *************************************************************
Declare String(*struc, Offset)
; ------------------------------------------------------------
Structure Bidule
Texte.s ; Byte 0+4 pour .s
Valeur1.l ; Byte 4+4 : .l
Valeur2.q ; Byte 4+8 : .q
Valeur3.s ; Byte 12+4 : .s
EndStructure
; ------------------------------------------------------------
Test.Bidule\Texte = "Bof ceci est un test" ;
Test\Valeur1 = 10 ;Test
Test\Valeur2 = 11
Test\Valeur3 = "12"
; ----------------------------------------- ; Dans le cas d'une structure Test.Bidule\etc... Test=Adresse du Pointeur de la Structure soit ici
Debug "--------- Avant -----------" ; PeekL(Test) donne l'adresse du premier pointeur qui contient le l'adresse du premier élément idem :
; ;
Debug "Avant -"+Str(Test) ; Ici "Test" c'est l'étiquette de l'adresse qui contient
; L'adresse du premier élément de la STRUCTURE...
; La preuve c'est que l'adresse trouvée
Debug "Avant -"+Str(PeekL(Test)) ; Là est la même que celle ci-dessous
Debug " ---------------------------------" ; trouvée elle grace à "@Test.Bidule\Texte"
Debug "Avant -"+Str(@Test.Bidule\Texte) ; Adresse du premier élément de la structure....
; Tandis que la chaine commence ou le pointeur "POINTE"...
Debug "Avant -"+PeekS(@Test.Bidule\Texte) ; Affichage de la chaine à partir de son adresse...
Debug Test\Valeur1 ;
Debug Test\Valeur2 ; ON confond souvent l'adresse des pointeurs
Debug Test\Valeur3 ; AVEC l'adresse des données qu'ils pointent....
; ---------------------------------------------------------------------------------------
Debug "Valeurs passée @Test = "+Str(@Test) ; Adresse du début de la Structure
Debug "Valeurs passée OffsetOf(Bidule\Texte)= "+Str(OffsetOf(Bidule\Texte)) ; décallage obtenus avec "OffsetOf(n)" le premier =0
Debug "Valeurs passée OffsetOf(Test\Valeur1)= "+Str(OffsetOf(Bidule\Valeur1)) ; ici ce sera 0 précédent + 4= 4 => premier de Val1
Debug "Valeurs passée OffsetOf(Test\Valeur2)= "+Str(OffsetOf(Bidule\Valeur2)) ; 4 précédent + 4 = 8 => premier de Val2
Debug "Valeurs passée OffsetOf(Test\Valeur3)= "+Str(OffsetOf(Bidule\Valeur3)) ; 8 précédent + 8 = 16 => premier de Val3
; ---------------------------------------------------------------------------------------
Debug "avec PeekS : "+PeekS(PeekL(@Test)) ; Affichage de la chaine à partir de son adresse...
Debug "avec PeekL : "+Str(PeekL(@Test+OffsetOf(Bidule\Valeur1))) ; Affichage avec OffsetOf... 4
Debug "avec PeekQ : "+Str(PeekQ(@Test+OffsetOf(Bidule\Valeur2))) ; Affichage avec OffsetOf... 8 = 4 + 4
Debug "avec PeekS : "+PeekS(PeekL(@Test+OffsetOf(Bidule\Valeur3))) ; Affichage avec OffsetOf... 16 = 8 + 8 de .q)
; ----------------------------------------------------------------------------------------------------------------------------------------
; ATTENTION: OffSetOf(expression) donne la position dans la structure du pointeur de la donnée.
;
; Ex: 'ICI "OffsetOf(Test\Valeur2) donne 8...
; Ce qui veux dire que le pointeur de Valeur2 se trouve à "PeekL(Test)+8"
; ou dans ce qui précéde à "@Test+8" ou en faisant PeekQ(@Test+8) doit donner la valeur de variable = 11
; ----------------------------------------------------------------------------------------------------------------------------------------
String(@Test, Offset)
; ----------------------------------------------------------------------------------------------------------------------------------------
;
Debug "--------- Après Procédure -----------"
Debug Test\Texte
Debug Test\Valeur1
Debug Test\Valeur2
Debug Test\Valeur3
;
; ------------------------------------------------------------
;Procedure String(*struc, Offset)
Procedure String(*struc, Offset)
Debug "--------- Dans procédure -----------"
*str.STRING = *struc+Offset
Debug "Entrèe 1- "+*str\s
*str\s = "Bonjour les petits enfants, je vous aime. Vous voulez des gateaux ?"
Debug "Sortie 2- "+*str\s
EndProcedure
;
Il est vrai que c'est plus simple aussi de passer les STRING dans les derniers point de la structures c'est plus facilement "extensible"...
Ou alors simplement utiliser des tableaux comme je l'ai fait avec KCC... Mais qui lui à compliqué un peu plus...
----------------------------------
Pourquoi compliqué ?
Parce qu'il voulait passer un tableau à une DLL...
Puis que celle-ci éventuellement modifie le tableau
Et enfin être récupéré modifié ou non par le module appelant...
Et en plus que cela soit utilisable par VB aussi... ???
Dans ce cas les pointeurs sont utilisé pour passer un "repère mémoire" au lieu des tableaux eux même.
Bref, ça à été fait pour PB...
Comme ci-dessous si ça peut vous être utile...
*********************************************************
Premier cas sans Tableau :
Code : Tout sélectionner
; ***************************************************
; Exemple de controle de la mémoire par : (GeBonet)
; Je suis : "AppelExempleMem01.PB ou Exe"
; PB 4.40 Beta 3
; -------------------------------------------------------------------;
; OBJET : Dans cet exemple les données sont d'abord
; écrit dans la mémoire client par le programme client
;
; On passe l'adresse et le nombre à la Dll pour y être traité...
; et au retour nous avons le résultat qui dans ce cas est
; une inversion des mots envoyé...
; *****************************************************
; Par facilité les données viennent ici d'un espace DATA
; mais pourraient venir d'une base de données, d'encodage
; ou d'un tableau généré... etc.
; ---------------------------------------
; Dans la Dll, il va de soit que les données passé peuvent aussi
; subir n'importe quel traitement, tri, sauvegarde particulière etc...
; ---------------------------------------
; L'objet principal étant de montrer la facilité d'envoyer des données
; à une Dll et de le récuperer en retour...
; ****************************************************
#Bibliotheque=0 :
OpenLibrary(#Bibliotheque,"ExempleMem01.dll") ; Ouvre la Dll devant lire la mémoire.........
If OpenConsole() ; Ouvre pour afficher
Taille=?FinDonne-?DebutDonnee ; Calcul de la Taille de la zone des DATA...
; ;
*MemoryID = AllocateMemory(Taille+100) ; Réservation de la mémoire utile et son Adresse + 100 (réserve)
*TamponMem=*MemoryID ; Garde une copie de l'adresse originale
CopyMemory(?DebutDonnee, *MemoryID, Taille) ; Transfert de la zone DATA vers la mémoire réservée
; On pourrait dans ce cas travailler directement sur la zone DATA...??
PrintN("=========Debut Client ==========");
; --------------------------------------------------------------;
Num=70 ; 70 = 14 ligne de 5 mots... (Idem Data)
;
; Lecture des DATA avec PeekS(...) Avant d'aller dans la DLL....
For i=1 To Num
Mot$=PeekS(*MemoryID+Resultat) ; Lecture des données à la nouvelle adresse mémoire
PrintN(Mot$) ; Affiche le mots lu à partir de sa nouvelle place...
Resultat + MemoryStringLength(@Mot$)+1 ; Incrémente le pointeur de la longueur du mots lu
k=k+1:If k=5:PrintN(" "):k=0:EndIf ; Un espace entre chaque groupe de 5 mots lus...
Next i ; qui peu symboliser des éléments d'un tableau...
; --------------------------------------------------------------;
PrintN("=========Fin Client ============")
PrintN("")
PrintN(" Appel de la DLL ")
; --------------------------------------------------------------; APPEL DE LA DLL
;
CallFunction(0,"CreateArray",*TamponMem, Num) ; Appel Dll qui devrait afficher la même zone mémoire
; ; Puis inverser les mots lu et les réécrire à l'envers
; --------------------------------------------------------------;
PrintN("========= FIN DLL Resultat =====")
PrintN(" lecture des mots inversé par la Dll...")
Num=70:*MemoryID=*TamponMem
Resultat=0:k=0 ; Réinitialisation des pointeurs et compteurs...
;
; Retour de DLL Et on va relire la mémoire que la DLL à Modifé...
;
For i=1 To Num ; Et relecture de la mémoire qui cette fois devrait avoir
Mot$=PeekS(*MemoryID+Resultat) ; être modifié par la Dll Lecture à la nouvelle adresse des données
PrintN(Mot$) ; Affiche le mots lu à partir de sa nouvelle place... pour confirmer
Resultat + MemoryStringLength(@Mot$)+1 ; Etc... Idem ci dessus
k=k+1:If k=5:PrintN(" "):k=0:EndIf ; Il va de soit que les "Mot$" peuvent être des élément d'un Tableau...
Next i ; Ici on évite tout bonnement de passer le tableau...
PrintN("========= FIN programme ======")
PrintN("Appuyez sur [Entree] pour quitter")
Input()
CloseConsole()
EndIf
End
; -------------------------------------------------------------------------------
DataSection
DebutDonnee:
Data.s "Sujet","Titre","NomFamille","Nom Editeur","AnneeCopyright"
Data.s "Tourisme","Salvador da Bahia : 100 Colorfotos","Richter","Alpina-Ceu azul de Copacabana","2000"
Data.s "Histoire","Fisionomía historica de Chile","Eyzaguirre","Editorial universitaria","1999"
Data.s "Poesie","Oeuvres completes. Tome premier","Boileau","Hachette","1880"
Data.s "Vie pratique","Manuel scout des arbres","Vieux Castor","Au Lasso (edition Scoutes)","1938"
Data.s "Album enfant","Nouvelles aventures du petit diable Malice, Les","Scheggia","Chagor","1959"
Data.s "Enseignement","Allemand sans peine","Cherel","Assimil","1960"
Data.s "Album enfant","Album des jeunes 1961","Collectif","Selection du Reader's Digest","1960"
Data.s "Religion","Sainte Bible, La","Collectif","Cerf","1961"
Data.s "Essai","Presence de Camus","Simon","Renaissance du livre","1961"
Data.s "Biographie","Napoleon","Bainville","Librairie generale française","1965"
Data.s "Theatre","Caligula (suivi de) Le malentendu","Camus","Librairie generale française","1966"
Data.s "Roman policier / espionnage","Toute la verité","West","Librairie generale française","1966"
Data.s "Theatre","Caligula (suivi de) Le malentendu","Simon","Librairie generale française","1966"
FinDonne:
EndDataSection
; ----------------------------------------------------------------------------------------
Partie de la DLL avec ce premier CAS !
Code : Tout sélectionner
;*************************************************************
; DLL : à compiler comme "ExempleMem01.Dll"
; ************************************************************
ProcedureDLL AttachProcess2(Instance)
;-----------------------------------------------------------------------
; Initialisation
; START DLL PROGRAMME
;-----------------------------------------------------------------------
EndProcedure
; ************************************************************
; ************************************************************
; Corps de la DLL
; ************************************************************
ProcedureDLL CreateArray(*Pointeur, Num)
If OpenConsole()
PrintN("=======-DEBUT DLL -========")
PrintN("Pointeur reçus==>"+Str(*Pointeur))
PrintN("----------------------------------------------")
For i=1 To Num ; 70 = 14 ligne de 5 mots... (Idem Data)
Mot$=PeekS(*Pointeur+Resultat) ; Lecture à la nouvelle adresse des données
PrintN(Mot$) ; Affiche le mots lu à partir de la place en mémoire...
;
Enver$=ReverseString(Mot$) ; Inverse le mot ... pour montrer qu'on a fait quelque chose....
PokeS(*Pointeur+Resultat,Enver$) ; ***==>>> Et l'écrit à la même place
;
Resultat + MemoryStringLength(@Mot$)+1 ; Incrémente le pointeur de la longueur du mots lu
k=k+1:If k=5:PrintN(" "):k=0:EndIf ; Un espace entre chaque groupe...
Next i ;
PrintN("")
PrintN("----- FIN DLL ------ *" )
EndIf
; -------------------------------------------------------------------
ProcedureReturn
EndProcedure
; ************************************************************
; ************************************************************
; Detache la DLL
; *******************************************************
ProcedureDLL DetachProcess2(Instance)
; fin de la DLL
EndProcedure
; *********************************************************
Deuxième cas AVEC TABLEAU
Ici les deux partie sont ensemble pour faciliter le test mais on peut créer la DLL et modifier l'appel pour que cela fonctionne....
Code : Tout sélectionner
; **************************************************************************************
; Ensemble des deux parties : ==> Appel_Dll_Tableau.pb
; ET ==> Dll_AvecTable.pb (Dll)
; **************************************************************************************
; Programme de Test Sous PB Version 4.31 : GeBonet
; Appel_Dll_Tableau.pb 22/09/2009
; -------------------------------------------------------------------------------------------------------
; Objet : 1- Passage de donnée entre un tableau du programme principal ver DLL
; 2- Modification dans Dll pour montrer qu'il se passe bien quelque chose
; 3- Retour au programme principal et affiche le Tableau Modifié.....
; ****************************************************************************************
#Dim1=20
Global Dim ArrayA.s(#Dim1) ; Ce sera une 4ième forme.
; -----------------------------------------------
; Programme Client de la DLL
; -----------------------------------------------
#Bibliotheque=0
; OpenLibrary(#Bibliotheque,"Dll_AvecTable.dll") A LIBERER SI APPEL DLL
Declare CreateArray(*Pointeur,nb)
; -------------------------------------------------------------------------------------
Restore DebutDonnee
;
If OpenConsole()
; ----------------------------------------------------------------------------------------
PrintN( "======= AVANT Appel DLL==========")
PrintN("")
For i=0 To #Dim1-1
Read.s ArrayA(i) ; adresse Variable du tableau
PrintN("Adresse Initiale : "+Str(@ArrayA(i))+" " +ArrayA(i))
Next i
PrintN( "=============================")
PrintN("Appuyez sur [Entree] pour Appel DLL")
Input()
;**************************************************************************
;
;*adresse=CallFunction(#Bibliotheque,"CreateArray", @ArrayA.s(),#Dim1) ; A LIBERER SI APPEL DLL
*adresse=CreateArray(@ArrayA.s(),#Dim1) ;
;
;**************************************************************************
ArrayA.s()=*adresse ; Récupère l'adresse du tableau de la DLL
PrintN("")
PrintN("======= Apres Appel DLL ==========")
PrintN("")
PrintN("Adresse du tableau de la Dll = "+Str(*adresse))
For i = 0 To #Dim1-1 ; adresse Variable extrait de l'adresse du tableau initial
PrintN("Au retour ===> " + Str(i)+" Le tableau "+ArrayA(i))
Next
PrintN("")
PrintN("======== FIN =========")
PrintN("Appuyez sur [Entree] pour quitter")
Input()
; --------------------------------------------------------------------------------------------
EndIf
CloseLibrary(#Bibliotheque)
CloseConsole()
End
;-------------------------------------------------------------------------
DataSection
DebutDonnee:
Data.s "Sujet","Titre","NomFamille","Nom Editeur","AnneeCopyright"
Data.s "Tourisme","Salvador da Bahia : 100 Colorfotos","Richter","Alpina-Ceu azul de Copacabana","2000"
Data.s "Histoire","Fisionomía historica de Chile","Eyzaguirre","Editorial universitaria","1999"
Data.s "Poesie","Oeuvres completes. Tome premier","Boileau","Hachette","1880"
Data.s "Vie pratique","Manuel scout des arbres","Vieux Castor","Au Lasso (edition Scoutes)","1938"
Data.s "Album enfant","Nouvelles aventures du petit diable Malice, Les","Scheggia","Chagor","1959"
Data.s "Enseignement","Allemand sans peine","Cherel","Assimil","1960"
Data.s "Album enfant","Album des jeunes 1961","Collectif","Selection du Reader's Digest","1960"
Data.s "Religion","Sainte Bible, La","Collectif","Cerf","1961"
Data.s "Essai","Presence de Camus","Simon","Renaissance du livre","1961"
Data.s "Biographie","Napoleon","Bainville","Librairie generale française","1965"
Data.s "Theatre","Caligula (suivi de) Le malentendu","Camus","Librairie generale française","1966"
Data.s "Roman policier / espionnage","Toute la verité","West","Librairie generale française","1966"
Data.s "Theatre","Caligula (suivi de) Le malentendu","Simon","Librairie generale française","1966"
FinDonne:
EndDataSection
; ************************************************************
; LA DLL ..............
; ************************************************************
ProcedureDLL AttachProcess2(Instance)
; ------------------------------------------------------------------------
; Initialisation
; START DLL PROGRAMME
; Dll_AvecTable.pb => Dll_AvecTable.Dll
; -----------------------------------------------------------------------
Global Taille
Global Dim ArrayA.s(Taille) ; Absolument necessaire pour faire exister
Global Dim ArrayB.s(Taille) ; le tableau pour la DLL avant même de recevoir quelque chose
EndProcedure
; ************************************************************
; ************************************************************
; Corps de la DLL
;
; Elle lit un tableau ArrayA.s(n) envoyé par l'appelant
; qu'elle place dans un tableau à elle qui est ArrayB.s(n)
; et renvois l'adresse de son tableau ArrayB.s()
; ************************************************************
ProcedureDLL CreateArray(*Pointeur,nb) ;
Dim ArrayB(nb)
ArrayA.s()=*Pointeur
Taille=ArraySize(ArrayA())
; --------------------------------------------------------------------
; ATTENTION : Affiché si : OpenConsole() est utilisé
; --------------------------------------------------------------------
If OpenConsole()
PrintN("=======-DEBUT DLL -========")
PrintN("Adresse dans dll : "+Str(*Pointeur)) ; @ArrayA(0)
PrintN("----------------------------------------------")
PrintN(" Taille de ArrayA() dans DLL ="+Str(Taille))
For i=0 To Taille-1 ; ICI IL N'Y A QU'UN PEEK
ArrayB(i)=PeekS(@ArrayA(i)) ; Prise dans la mémoire de ArrayA(i) de la chaine qui s'y trouve...
PrintN("ArrayB("+Str(i)+") ="+ArrayB(i)) ; Ici il s'agit bien du tableau ArrayB(i) que l'on affiche...
Next i
PrintN("")
PrintN("> Inverse les mots dans DLL AVANT renvois... ")
Input()
; -------------------------------------------------------------------
; C'est ICI que le travaille dans la DLL peux commencer
; -------------------------------------------------------------------
For i=0 To Taille-1 ; Mais le travaille de la DLL Va s'éffectuer
For j=Len(ArrayB(i)) To 1 Step-1 ; Boucle d'inversion
Mot2$+Mid(ArrayB(i),j,1) ; Inversion...
Next j ;
ArrayB(i)=Str(i)+" - "+ Mot2$ ; On replace la MODIFICATION... qui sera lu dans le corps du programme...
PrintN(ArrayB(i)) ; On affiche le contenu du tableau
Mot2$=""
Next i
PrintN("")
PrintN("----- FIN DLL ------ *")
Input()
; ----------------------- Fin du travail de la Dll ----------------
*Adresse=@ArrayB()
;CloseConsole()
EndIf
ProcedureReturn *Adresse
EndProcedure
; ************************************************************
; ************************************************************
; Detache la DLL
; ************************************************************
ProcedureDLL DetachProcess2(Instance)
; fin de la DLL
EndProcedure
; ***********************************************************
Voilà, voilà,
C'est peut-être du déjà connus mais pas forcément montré comme ça
