CopyMemory Lib "kernel32" Long to string, Rein à faire cela plante PARTOUT ! ! !

Résolu
rebixav Messages postés 130 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 28 janvier 2013 - 24 juin 2011 à 12:58
rebixav Messages postés 130 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 28 janvier 2013 - 1 sept. 2012 à 15:56
Il y en a marre,... rien à faire cette API plante dans tout les sens, et je suis pas le seul à l'avoir remarqué ! ! !
Même les plus expert en perde leur langage (VB6, ou même C)

Voici le programme que je n'arrive pas à faire marcher !
ATTENTION N'oubliez pas d'enregistrer aprés l'avoir mis dans votre VB !

' dans un module en déclaration
Type un_type_
chaine As String
End Type
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (destination As Any, ByVal Source As Any, ByVal longueur As Long)

' dans un boutons Command1
Dim un_type As un_type_
Dim ch As Long
Dim chaine As String
Dim chaine2 As String * 4
Dim chaine3 As String * 100

chaine = Chr$(10) + Chr$(0) + Chr$(0) + Chr$(0)
chaine2 = Chr$(10) + Chr$(0) + Chr$(0) + Chr$(0)
chaine3 = Chr$(10) + Chr$(0) + Chr$(0) + Chr$(0)
un_type.chaine = Chr$(10) + Chr$(0) + Chr$(0) + Chr$(0)
'et oui en plus le chiffre le plus bas est a gauche je pensé qu'il était à droite !
ch = 30000
l& = Len(chaine)
l4& = Len(un_type.chaine)
l2& = Len(chaine2)
l3& = Len(chaine3)
l5& = Len(ch)

' n'oubliez pas un text1
'CopyMemory ch, chaine, 4: Text1 = ch

'CopyMemory chaine, ch, 4: Text1 = chaine
'CopyMemory un_type.chaine, ch, 4: Text1 = un_type.chaine
'CopyMemory chaine2, ch, 4: Text1 = chaine2
CopyMemory chaine3, ch, 4: Text1 = chaine3

et là si vous le lancé, vb6 plante !
avec tout les CopyMemory , sauf le 1er mis à part !
en faite je n'arrive pas à mettre un chiffre de type LONG dans un STRING

PS:pas de blag du genre pourquoi pas :
chaine=str$(ch) => donne : " 30000"
ou CStr(ch) => donne : "30000"
et moi je veux du genre " ù*" en faite seulement 4octets pour tout
les chiffre, même les plus long comme 2 147 483 647 !
cela me permetterez à moi comme beaucoup de transférer des chaines par reseau ou autres avec seulement des chaine entière, string+integer+long+long+integer,...ETC.

Bref pourquoi cela plante, que faire pour éviter cela ???!
merci à tous, car je pense que cela en aideras plus d'un !

12 réponses

cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
24 juin 2011 à 20:17
Méfie toi aussi de VB : Quand tu écris
a3% = ch& \ 65536
le compilateur peut décider que 65536 est un entier (-1 en fait), et du coup, perturber ce genre de calcul, surtout quand il voit :
a3% : Integer
ch% : Long
Il doit ranger dans un entier le résultat d'un calcul sur 2 long

Solutions :
- Ajouter le type de variable derrière le chiffre :
a3% = ch& \ 65536 &

- déclarer explicitement les conversions :
a3% = CInt(ch& \ 65536&)

Mais je t'assure que toutes ces fonctions peuvent aisément être remplacées par le passage par l’hexadécimal qui simplifie beaucoup de chose, exemple :

Passer d'un entier à une chaine :
Chaine$ = Hex$(monEntier%) donnera 2 octets maxi

Passer d'un long à une chaine :
Chaine$ = Hex$(monLong&) donnera 4 octets maxi

Si tu veux absolument que tous tes integers soient sur 2 octets et tes longs sur 4 octets, il suffit de remplir avec des 0 devant :
Chaine$ = Right$(String$(4, "0") & Hex$(monEntier%), 4)
Chaine$ = Right$(String$(8, "0") & Hex$(monLong&), 8)

Et pour passer de String (*) à Integer ou Long ?
(*) représentant un hexa
Ultra simple :
monLong& = Val("&H" & maChaine$)
3
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
24 juin 2011 à 16:48
Salut

Faut pas s'énerver

Un peu de lecture http://oreilly.com/catalog/win32api/chapter/ch06.html#61581 et <là (paragraphe String)>

L'adressage des chaines, sous VB6, est de plusieurs types :
- Les chaines limitées en longueur, comme As String * 4
- Les chaines non limitées, comme As String
- Les chaines encapsulées dans une structure (Type).

Étudie les liens que je t'ai passé, ils sont très instructifs.
Il faudra utiliser VarPtr pour récupérer les adressages.

Dans ce genre de manipulations, il est très important de dimensionner correctement les variables - passe en déclaration obligatoire des variables - voir Options (Option Explicit en tête des pages de code)

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
24 juin 2011 à 16:52
"[i]moi je veux du genre " ù*" en faite seulement 4octets pour tout
les chiffre, même les plus long comme 2 147 483 647 !/i"

4 octets, c'est la taille d'une variable Long VB6.
Tu ne pourras pas en ajouter d'autres à l'intérieur.
Si tu veux envoyer ton chiffre sur un réseau, envoie le Long.
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
24 juin 2011 à 17:03
Je reviens sur ça :
chaine = Chr$(10) + Chr$(0) + Chr$(0) + Chr$(0)
Chaque chiffre, à l'intérieur des Chr$, représente un Byte ou octet (0-255 ou 00 à FF).
Si tu veux transférer ton Long (4 octets) sous cette forme, le plus simple :
(exemple avec le chiffre 849 736 480)

- Conversion su Long en Hexa : monHexa$ = Hex$(monLong&)
Cette chaine aura, au maximum, 4 octets, soit 00 00 00 00 (pour le chiffre 0) ou encore FF FF FF FF (pour le chiffre ... -1)
Notre exemple donnera 32 A5 F3 20

- Une fois que tu as ta chaine de 8 caractères (0-9 et A-F), il te suffit de convertir chaque partie en byte :
monByte1 = cbyte(val("&h" & "32"))
monByte2 = cbyte(val("&h" & "A5"))
monByte3 = cbyte(val("&h" & "F3"))
monByte4 = cbyte(val("&h" & "20"))

- Ensuite seulement, tu pourras envoyer les Chr$ avec chacun de Bytes

Mais rappelle-toi que les Sockets (*) savent transférer n'importe quel type de données, pas seulement les String; tu peux très bien expédier un tableau de Bytes, un tableau de 4 Bytes par exemple.

(*) Champion du monde de boule de cristal 2005-2006
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
rebixav Messages postés 130 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 28 janvier 2013
24 juin 2011 à 18:06
Super, en plus je commence à te connaitre sur VBFRANCE, j'ai beaucoup de chance d'être tombé sur toi !

1 - J'avais peur que tu me réponde, sort la bible du PC et mange les 150 pages en rapport avec la mémoire,... snifs !
Je suis pris par le temps et en plus je suis loin d'être doué en anglais !
... mais bon si la solution est là je regarderais cela un peu plus tard, en attendant je me suis fait au bout de deux jours de galère avec copymemory, 4 function en 15 minutes, qui me serve déjà bien !

Public Function long_to_string$(ByVal ch&)
a4% ch& \ 16777216: ch& ch& Mod 16777216
a3% ch& \ 65536: ch& ch& Mod 65536
a2% ch& \ 256: a1% ch& Mod 256
long_to_string$ = Chr$(a1%) + Chr$(a2%) + Chr$(a3%) + Chr$(a4%)
End Function

Public Function integer_to_string$(ByVal ch%)
a2% ch% \ 256: a1% ch% Mod 256
integer_to_string$ = Chr$(a1%) + Chr$(a2%)
End Function

Public Function string_to_integer%(ByVal chaine$)
string_to_integer% = asc(Mid$(chaine$, 2, 1)) * 256 + asc(Mid$(chaine$, 1, 1))
End Function

Public Function string_to_long&(ByVal chaine$)
string_to_long& = asc(Mid$(chaine$, 4, 1)) * 16777216 + asc(Mid$(chaine$, 3, 1)) * 65536 + asc(Mid$(chaine$, 2, 1)) * 256 + asc(Mid$(chaine$, 1, 1))
'cette putain de copymemory2 ne marche pas !!!!!!!!!!!!!!!
Exit Function
CopyMemory2 string_to_long&, chaine$, 4
End Function

PS: comme tu voit dans la function string_to_long&, il était prévue de mettre une copymemory, mais bon je me suis pour le moment resigné, mais je sais que cette copymemory est limitte indispensable !

2 - en faite je pense que pour utilisé winsock cétait mieux comme cela :
Data$ = data_fichier_envoie.deux_dernier_octets + integer_to_string$(data_fichier_envoie.long) + data_fichier_envoie.Data
Winsock(Index).SendData "fe" + Data$

comme cela en une ligne winsock, UNE chaine envoyé j'ai :
les deux dernier octet du tempon d'envoie, la taille de ce tempon, et évidement le tempon !

comme cela je récupérer de cette manière là de l'autre côté

data_fichier_recep.deux_dernier_octets = Left$(Data$, 2)
data_fichier_recep.long string_to_integer%(Mid$(Data$, 3, 2)): L% Len(Data$) - 4
data_fichier_recep.Data = Right$(Data$, L%)

je sais il existé plein d'autre solution, c'est cela la magie du langage évolué, chacun un peu sa manière pour faire les mêmes chose, la différence, la taille du code, et sa vitesse,... moi depuis quelque jours, je fatigue un peu, je suis en mode je m'embete plus
d'où ces 4 procédure en attendant CopyMemory qui doit être plus rapide !

à la base j'aurrais même voulue faire comme cela !
Private Type data_fichier_
deux_dernier_octets As String * 2
long As Integer
Data As String
End Type
dim Type data_fichier as Type data_fichier_
je remplie les variable,...
Winsock(Index).SendData "fe" + Type data_fichier
mais là encore je ne peut pas, donc je voulais faire
CopyMemory data$,Type data_fichier,len(Type data_fichier)
mais là cela plante !
le monde n'est pas simple


PS : Au faite est-ce que tu sait si sur une mémoire de type LONG si la valeur la plus forte est bien à droite, moi je croyais qu'elle était à gauche ?!

J'essaierais de lire ce que tu m'as donner sur CopyMemory !
sauf si tu peut me corriger la ligne de commande :
" CopyMemory data$,Type data_fichier,len(Type data_fichier) "
0
Profil bloqué
24 juin 2011 à 18:35
Salut

tu as écrit : 'cette putain de copymemory2 ne marche pas !!!!!!!!!!!!!!!
Exit Function
CopyMemory2 string_to_long&, chaine$, 4

Les paramètres source et destination doivent être du même type
Là tu as une variable numérique long et une variable chaine de caractères (String)
Comment veux-tu que cela marche ?


La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi.

GRENIER Alain
0
Profil bloqué
24 juin 2011 à 18:48
tu as écrit :
PS : Au faite est-ce que tu sait si sur une mémoire de type LONG si la valeur la plus forte est bien à droite, moi je croyais qu'elle était à gauche ?!

La réponse
Windows écrit les nombres en mémoire en commençant toujours par les octets de poids le plus faible
Un exemple: soit le nombre décimal 256 qui s'écrit en héxa 0100 sur 2 octets
si Windows range ce nombre en mémoire à l'adresse 543 on aura 00 à l'adresse 543 et 01 à l'adresse 544.
Ceci est transparent pour l'utilisateur à moins que l'on recherche soit même des valeurs spécifiques en mémoire avec un éditeur héxadécimal
Dans notre cas pour rechercher la valeur 256 il faut chercher avec l'éditeur héxadécimal la suite d'octets 00 et 01 et nous l'inverse.



La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi.

GRENIER Alain
0
Profil bloqué
24 juin 2011 à 18:49
Pardon : et non l'inverse bien sûr !


La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi.

GRENIER Alain
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
24 juin 2011 à 20:20
PS : Les décompositions sont toujours représentées avec le poids faible à droite, comme pour les chiffres décimaux.
0
rebixav Messages postés 130 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 28 janvier 2013
28 juin 2011 à 13:08
Désolé j'étais malade, et en plus qu'elle chaleur...

merci pour ta réponse Jack, je regarderez lequel est le plus rapide !
et oui, je ne peut m'empêcher de vouloir faire des procédure sans pense au cout de vitesse que cela peut manger, faut dire que j'ai commencé le BASIC à l'époque du VG5000 et du CPC amstrad, le tout en cassette !

par contre jack que veut tu dire par :

PS : Les décompositions sont toujours représentées avec le poids faible à droite, comme pour les chiffres décimaux.

car si vous parlez de la même chose pourquoi GALAIN à ecrit :
Windows écrit les nombres en mémoire en commençant toujours par les octets de poids le plus faible
(donc a gauche)
... heuuuu... A gauche ou A droite !
Faudrais savoir !
Moi je m'en fiche cela changeras rien à ma procédure ! Mais j'aime bien faire les choses, il y a des regles !

PS : quelque connais un SITE de tout les bug ridicule de windows
j'en ais queque un en tête, mais c'est dommage, j'aimerais les faire partager !
0
rebixav Messages postés 130 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 28 janvier 2013
28 juin 2011 à 13:36
Bon Revenons au sujet principale qui a était posté !
le COPYMEMORY c'est DELA MER... pardon !

je suis prêt à ecrire une procédure du genre

public sub copymemory2(chaine$,long)
CopyMemory chaine$,long,4 <<<=== à corrigé bien sure !
end sub
au lieu de : CopyMemory chaine, ch, 4: Text1 = chaine
puisque cela plante VB6

ou même plus sympa pour la prog :
Public Function long_to_string$(ByVal ch&)
CopyMemory long_to_string$,ch&,4 <<<=== à corrigé bien sure !
end sub

...
j'ai chercher un peu partout et je n'ais pas trouvé du procédure parfaite permétant de faire
ma_var&=chaine$ sans bugé !

moi j'ai fait cela sinon : (pas fine!)
Public Sub copie_mem(ByVal Source As Variant, destination As Variant)
a$ = "c:\fichier_tempon_de_copie_mem" + Date$ + Str$(Timer) + ".tmp"
nfich% = FreeFile: Open a$ For Binary As #nfich%
Put #nfich%, , Source
Get #nfich%, 1, destination
Close #nfich%: Kill a$
End Sub

mais je ne passe pas encore tout, un type personalisé ne passe pas,
comment je pourais faire avec un type personalisé, moi j'ai ecrit:
ByVal Source As Variant,... il y a pas as any dans VB6 !
je serais obliger d'ecrire cela:

a$ = "c:\fichier_tempon_de_copie_mem" + Date$ + Str$(Timer) + ".tmp"
nfich% = FreeFile: Open a$ For Binary As #nfich%
Put #nfich%, , ma_type
ma_chaine$=string$(len(ma_type),"o")
Get #nfich%, 1, ma_chaine$
Close #nfich%: Kill a$

au lieu de :

copie_mem ma_type, ma_chaine$

ma perso cela me gene beaucoup lorsque l'on fait de la grosse PROG !
1 ligne c'est tout de même mieux que 6 !


bref si quelqu'un sait au moins comment utilisé copymemory avec les STring et LONG, mélangé, ou les type personalisé, ou il y a des long, des single, des string vers une seul string ! JE SUIS PRENEUR ! ! !

merci...
0
rebixav Messages postés 130 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 28 janvier 2013
1 sept. 2012 à 15:56
En faite, je crois que j'avais oublié de donner la réponse !

depuis je me suis des procédure très intéressante pour transférer des tableau entier de long, single,...etc vers des strings!

je ne peut malheureusement pas les fournir, il sont encré dans des module complexe !

mais la soluce tient en un mot



BYVAL



voilà !

en revoir !

...

non sérieux en faite il faut utiliser copymemory comme cela :

CopyMemory desti_long(t1&), ByVal Source_String, l&

ou

CopyMemory ByVal desti_string, Source_long(position_debut), l&

ou


CopyMemory ByVal desti_string, ByVal Source_String, l2&

en faite lorsque vous voulez copier avec un string, vous devez utiliser "BYVAL" devant le String c'est tout !
rien d'autre !
0
Rejoignez-nous