Conversion de types de données 64 bits ==> 32 bits [Résolu]

Signaler
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
-
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
-
Violent Ken

Salut !
Voilà ce que j'aimerais faire : convertir un ensemble de deux variables long en une seule variable long.

Je sais que c'est pas clair, alors regardez l'exemple pour mieux comprendre ;)

Voici la structure FILETIME :

Public Type FILETIME
        dwLowDateTime As Long
        dwHighDateTime As Long
End Type

Elle contient deux long, dwLowDateTime et dwHighDateTime. Chacune des deux variables détermine respectivement les 32 derniers bits (donc à droite) et les 32 premiers bits (donc à gauche) d'une variable de 64 bits.

En fait, la valeur 64-bits représente dans mon cas le nombre d'intervalle de 100 nanosecondes écoulées depuis le 1er janvier 1601. Comme ce nombre dépasse la valeur maximale d'une long (qui va de – 2 147 483 648 à 2 147 483647, donc 4 294 967 296 valeurs différentes), il est stocké dans deux variables, chacune de type long.
 
dwHighDateTime contient le nombre de fois que dwHighDateTime a été rempli..... vous comprenez ?

Nombre total = 4 294 967 296 *dwHighDateTime + dwLowDateTime

En tout cas, c'est ce que j'ai compris... le problème est que la conversion des deux long en une seule long ne marche que pour de faibles valeurs de dwHighDateTime. Erf, je sens que ce n'est pas clair....

Pour ceux qui connaissent le C#, je cherche exactement ceci en VB6 :

 #include <winbase.h>
   #include <winnt.h>
   #include <time.h>

   void UnixTimeToFileTime(time_t t, LPFILETIME pft)
   {
     // Note that LONGLONG is a 64-bit value
     LONGLONG ll;

     ll = Int32x32To64(t, 10000000) + 116444736000000000;
     pft->dwLowDateTime = (DWORD)ll;
     pft->dwHighDateTime = ll >> 32;
   }

sauf qu'à la place d'une LONGLONG, j'aimerais une LONG dont la valeur est celle de la LONGLONG divisée par 10^7 (ce qui rentre donc dans une seule long)

En espérant que vous compreniez , merci, @+

8 réponses

Messages postés
3140
Date d'inscription
vendredi 14 mai 2004
Statut
Membre
Dernière intervention
11 mars 2019
25
Salut,

Il faut pas utiliser FILETIME mais passer directement par du Currency

Daniel
Messages postés
956
Date d'inscription
lundi 30 mai 2005
Statut
Membre
Dernière intervention
21 août 2014
1
Bonjour,


en vb6??? heu la y a malaise... tu peux pas passer par des chaines de caractères et faire une conversion après ??

-- Pourquoi faire simple quand on peut faire compliquer --
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Salut !

Passer par des chaines ? Tu veux dire concatener Str$(dwLowDateTime) et Str$(dwHighDateTime) ?

Ma foi, l'idée semble bonne, mais le type de structure 64-bits en présence ne marche pas comme cela il me semble.

Car mettre Str$(dwHighDateTime) devant Str$(dwLowDateTime) implique que dwLowDateTime est un coefficient multiplicateur de 10^n, et non de 4 294 967 296.

Euh, j'ai bien compris ton idée et tu as compris ma réponse ? ;)

En tout cas merci de m'aider ^_^
@+
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
64
tu peux utiliser l'API FileTimeToLocalFileTime

Renfield
Admin CodeS-SourceS- MVP Visual Basic
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Renfield ==> C'est déjà fait.

Mais je n'utilise pas FileTimeToSystemTime ; je veux garder une précision à la milliseconde (au mieux de 10^-7 secondes donnée par la strcture 64-bits) et pas une précision à la seconde (qui est renvoyée par FileTimeToSystemTime).

Je vous donne mon bout de code, je pense que vous comprendrez mieux.

Public Sub GetProcTimes(ByVal lPID As Long, ByRef KernelTime As Double, ByRef UserTime As Double, ByRef ProcessorTime As Double)
'obtient la consommation en temps processeur, séparé en temps noyau et temps utilisateur
'la somme est le temps processeur
Dim T0 As FILETIME, T1 As FILETIME, lHigh As Double, lLow As Double, lDefault As Double, lProcess As Double, lTime As Double



'FILETIME est une structure 64-bits composée de deux longs, chacun de 32 bits
'dwHighDateTime contient les 32 bits supérieurs, et dwLowDateTime les 32 bits inférieurs




'on récupère tout d'abord le "temps processeur nul", c'est à dire les temps du processus idleprocess (pid=0)
'c'est à dire les temps par défaut (auxquels vont s'ajouter les temps spécifiques à chaque processus)




'le type long comprend des entiers relatifs dont la plage s'étend de – 2147483648 à 2147483647
'il y a donc 2147483647+1+2147483648=4294967296 valeurs différentes
'dwHighDateTime représente donc sa valeur multipliée par la valeur maxi représentée par un long (4294967296)
Const lMax = 4294967296#




'le temps FILETIME est une structure 64-bits contenant le nombre d'intervalles de 100 nanosecondes écoulées depuis le 1/1/1601 2:00:00
'100 nanosecondes = 10^-7 secondes






'//KERNEL time
'//TEMPS par défault
'ouverture du processus idleprocess
lProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, 0) 'PID=0,
'obtient les temps
GetProcessTimes lProcess, T0, T0, T1, T0 't0 n'est pas utilisée car on ne garde que le temps kernel
'conversion
FileTimeToLocalFileTime T1, T1
lHigh = T1.dwHighDateTime
lLow = T1.dwLowDateTime
'calcule le temps en secondes (multiplie par 10^-7 pour récupérer le temps en secondes)
lDefault = (lMax * lHigh + lLow) / 10000000


'temps du processus concerné
'ouverture du processus concerné
lProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, lPID) 'PID=0,
'obtient les temps
GetProcessTimes lProcess, T0, T0, T1, T0 't0 n'est pas utilisée car on ne garde que le temps kernel
'conversion
FileTimeToLocalFileTime T1, T1
lHigh = T1.dwHighDateTime
lLow = T1.dwLowDateTime
'calcule le temps en secondes (multiplie par 10^-7 pour récupérer le temps en secondes)
lTime = (lMax * lHigh + lLow) / 10000000


'le temps noyau du processus est donc lTime-lDefault
KernelTime = lTime - lDefault


 


'//USER time
'//TEMPS par défault
'ouverture du processus idleprocess
lProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, 0) 'PID=0,
'obtient les temps
GetProcessTimes lProcess, T0, T0, T0, T1 't0 n'est pas utilisée car on ne garde que le temps user
'conversion
FileTimeToLocalFileTime T1, T1
lHigh = T1.dwHighDateTime
lLow = T1.dwLowDateTime
'calcule le temps en secondes (multiplie par 10^-7 pour récupérer le temps en secondes)
lDefault = (lMax * lHigh + lLow) / 10000000


'temps du processus concerné
'ouverture du processus concerné
lProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, lPID) 'PID=0,
'obtient les temps
GetProcessTimes lProcess, T0, T0, T0, T1 't0 n'est pas utilisée car on ne garde que le temps user
'conversion
FileTimeToLocalFileTime T1, T1
lHigh = T1.dwHighDateTime
lLow = T1.dwLowDateTime
'calcule le temps en secondes (multiplie par 10^-7 pour récupérer le temps en secondes)
lTime = (lMax * lHigh + lLow) / 10000000


'le temps user du processus est donc lTime-lDefault
UserTime = lTime - lDefault


 


'le temps processeur est la somme des temps kernel et user
ProcessorTime = UserTime + KernelTime
End Sub



J'ai bien commenté la fonction, je crois que c'est compréhensible.

Le problème est que le temps lDefault est mauvais pour les valeurs de dwHighDateTime trop élevées.

Mais sinon, çà marche très bien, j'ai comparé les valeurs retournées avec Process Explorer de Sysinternals, tout est bon.
Le but de la fonction, vous l'aurez compris, est de récupérer le temps processeur d'un processus défini par son PID.
(j'ai créé entièrement ce bout de code car je n'ai rien trouvé de tel sur le net, c'est à dire avec la précision à la milliseconde)

Merci, @+
Messages postés
956
Date d'inscription
lundi 30 mai 2005
Statut
Membre
Dernière intervention
21 août 2014
1
Heu oui en concaténant


(pour le reste ça mérite un source sur ce site...)

-- Pourquoi faire simple quand on peut faire compliquer --
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Hum, je vais expliquer mes doutes sur la méthode "concaténation" :

Si je pose les bits supérieurs à gauche de la string, cela veut dire que ce sont les multiples d'une puissance de 10.

Exemple : 
long gauche=123
long droite=456
Donc résultat=123456
Détail : résultat = 123*10^(longueur des longs=3)+456

Tandis que dans mon cas, ce serait 123*(taille maxi prise par un long signé)+456.




Concernant ce bout de code, oui, il ferait bien une source sur Vbfrance (quand il sera sans bug), mais ce n'est qu'une infime partie de ma source.
J'hésite à poster des morceaux de ma source, quoique ce serait une bonne idée (cette fonction étant encore inexistante sur ce site). Concernant la source elle même, elle est loin d'être finie, c'est un gros boulot.

Donc pour la concaténation, je vais essayer de suite, mais je reste perplexe.

@+
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Salut, tout d'abord désolé de ne pas avoir répondu plus tôt, mon FAI m'a planté toute l'après-midi d'hier, cette nuit, et encore ce matin.....

Concernant ta méthode.... çà marche nickel ! En plus çà diminue énormément le nombre de lignes de codes ! Excellent ! Je ne savais pas que l'on pouvait modifier les déclarations des APIs.

Merci beaucoup (et à tout ceux qui m'on aidé) , @+