OVH Cloud OVH Cloud

Chaine vers tableau de byte

19 réponses
Avatar
Jean-Marc
Bonjour chers collègues,

j'ai un besoin précis d'optimisation: Je dois convertir
une chaine en un table de Bytes.

J'ai écrit cette fonction, qui fonctionne très bien:

' s : une chaine
' szt : la longuue de cette chaine
' t() : le tableau de byte à remplir
Function CvrtStr2ByteArray(ByVal s As String, _
ByVal szt As Long, _
ByRef t() As Byte) As Boolean
Dim i As Long
Dim c As String

For i = 1 To szt
c = Mid$(s, i, 1)
If LenB(c) = 0 Then
t(i - 1) = CByte(0)
Else
t(i - 1) = CByte(Asc(c))
End If
Next i
CvrtStr2ByteArray = True
End Function

Connaitriez vous un moyen de faire cela, mais plus rapidement
que ne le fait cette implémentation naïve.
J'ai ici un vrai besoin d'optimisation, car cette fonction est
un facteur limitant dans un de mes programmes (Rabbit)
Note: la chaine en paramètre peut être très longeur (jusqu'à
plusieurs centaines de K) et j'appelle parfois cette fonction
plusieurs milliers de fois consécutivement.
Si vous aviez un moyen efficace, je suis preneur, sinon je ferais
une dll en C, mais je voulais éviter cela pour ce projet en
particulier.

Pour établir une comparaison, j'ai mesuré les performances de
ma fonction: 10 mesures de 100 appels avec une chaine aléatoire
de 65535 caractères.

Résultat: 37 millisecondes par appel de fonction.

Si on peut faire en dessous de 10 millisecondes, je prends :-)
Sinon, je fais une Dll :-(

--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr

9 réponses

1 2
Avatar
Picalausa François
"Jacques93" a écrit dans le message de news:

Picalausa François a écrit :
Tu as tout à fait raison, je m'est trompé sur ce coup... je pensais au
passage As Long + StrPtr (qui lui peut poser problème)




Sieste trop courte ? fais gaffe, en plus on perd une heure cette nuit.

:-D




Je dirais plutôt très peu de VB ces derniers temps (au profit de C, C++ et
C# cela étant ;-) ) ce qui tend à provoquer d'horribles mélanges
d'informations, du grillage de neurones, d'écriture de ; de manque de
pointeurs et... *se relève brusquement du clavier alors que des arcs
électriques (éclairs de génie?) lui sorte de la tête*

brrrzt... brrzt...

System restarting!

Private Declare function Areuh?

--
Picalausa François
Avatar
Jean-Marc
Merci François,

je vais essayer ceci également.

--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ;


"Picalausa François" a écrit dans le message de
news:
Hello,

Il y a une technique très efficace qui consiste à mapper un SAFEARRAY


sur ta
string...
Ceci évite de devoir allouer deux fois la mémoire (donc gain de temps)


et de
devoir recopier la chaine à chaque modification (ou d'effectuer les
modification en double) puisqu'on travaille sur la même zone


mémoire...

Reste à répéter : "Même en VB, je n'ai pas peur des pointeurs!" deux


ou
trois fois... ou pas!

Voici un bout de code illustrant la technique:
Option Explicit

Private Const FADF_HAVEVARTYPE = &H80
Private Const VT_I2 = 2
Private Const VT_UI1 = 17

Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type

Private Type SAFEARRAY
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
End Type

Private Declare Function VarPtrArray _
Lib "msvbvm60.dll" _
Alias "VarPtr" _
( _
Var() As Any _
) _
As Long
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" _
( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)

Private opsa As Long 'pointeur vers la safearray précédente
Private opvdata As Long 'pointeur vers les données précédentes
Private osb As SAFEARRAYBOUND 'bornes précédentes du tableau

Private Function MapSafeArrrayToString(psa As Long, strText As String)


As
Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
MapSafeArrrayToString = False

'Vérifie la validité des données en entrée
If ((StrPtr(strText) <> 0) And (psa <> 0)) Then
'Vérifie qu'on a bien démappé précédemment
If (opsa = 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal psa, LenB(sa))

'Demande une array typée en 1D non lockée
If ((sa.fFeatures And FADF_HAVEVARTYPE) And (sa.cDims = 1)


And
(sa.cLocks = 0)) Then
'Demande de plus que cette array soit typée As Byte ou


As
Integer
CopyMemory vt, ByVal (psa - 4), LenB(vt)
If (vt = VT_UI1) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),


LenB(osb))

'Remap le tableau
sab.cElements = LenB(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,


LenB(sab))

sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))

MapSafeArrrayToString = True
End If
End If
End If
End If
End Function

Private Function UnmapSafeArray() As Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
UnmapSafeArray = False

'Vérifie la validité des données en entrée
If (opsa <> 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal opsa, LenB(sa))

'Restaure les données
Call CopyMemory(ByVal opsa + LenB(sa), osb, LenB(osb))
sa.pvData = opvdata
Call CopyMemory(ByVal opsa, sa, LenB(sa))

'Oublie tout de ce qui s'est passé
opsa = 0
opvdata = 0
osb.cElements = 0
osb.lLbound = 0
End If
End Function

Private Function GetPsa(PPSA As Long) As Long
Call CopyMemory(GetPsa, ByVal PPSA, LenB(GetPsa))
End Function

Private Sub Form_Load()
Dim Blah As String
Dim byBlah() As Byte
Dim i As Long

ReDim byBlah(0)

Blah = "Hello World!"

'ATTENTION : jusqu'à UnmapSafeArray, il est préférable que
'Blah ne sorte jamais du scope
If MapSafeArrrayToString(GetPsa(VarPtrArray(byBlah)), Blah) Then
For i = LBound(byBlah) To UBound(byBlah)
Debug.Print Chr$(byBlah(i))
Next i

UnmapSafeArray
End If
End Sub

--
Picalausa François

"Jean-Marc" a écrit dans le message de


news:
4425260b$0$11427$
> Bonjour chers collègues,
>
> j'ai un besoin précis d'optimisation: Je dois convertir
> une chaine en un table de Bytes.
>
> J'ai écrit cette fonction, qui fonctionne très bien:
>
> ' s : une chaine
> ' szt : la longuue de cette chaine
> ' t() : le tableau de byte à remplir
> Function CvrtStr2ByteArray(ByVal s As String, _
> ByVal szt As Long, _
> ByRef t() As Byte) As Boolean
> Dim i As Long
> Dim c As String
>
> For i = 1 To szt
> c = Mid$(s, i, 1)
> If LenB(c) = 0 Then
> t(i - 1) = CByte(0)
> Else
> t(i - 1) = CByte(Asc(c))
> End If
> Next i
> CvrtStr2ByteArray = True
> End Function
>
> Connaitriez vous un moyen de faire cela, mais plus rapidement
> que ne le fait cette implémentation naïve.
> J'ai ici un vrai besoin d'optimisation, car cette fonction est
> un facteur limitant dans un de mes programmes (Rabbit)
> Note: la chaine en paramètre peut être très longeur (jusqu'à
> plusieurs centaines de K) et j'appelle parfois cette fonction
> plusieurs milliers de fois consécutivement.
> Si vous aviez un moyen efficace, je suis preneur, sinon je ferais
> une dll en C, mais je voulais éviter cela pour ce projet en
> particulier.
>
> Pour établir une comparaison, j'ai mesuré les performances de
> ma fonction: 10 mesures de 100 appels avec une chaine aléatoire
> de 65535 caractères.
>
> Résultat: 37 millisecondes par appel de fonction.
>
> Si on peut faire en dessous de 10 millisecondes, je prends :-)
> Sinon, je fais une Dll :-(
>
> --
> Jean-marc
> Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
> "There are only 10 kind of people
> those who understand binary and those who don't."
> mailto: remove '_no_spam_' ;
>




Avatar
Jean-Marc
"Jacques93" a écrit dans le message de
news:%
Bonjour Picalausa François,
Picalausa François a écrit :
> Hello,
>
> Si tu copymemory(strconv("a",vbFromUnicode)), tu auras la


description de
> caractère voulue (ANSI plutôt qu'UNICODE).
> Il ne faut pas oublier que VB stoque en interne les chaines en


UNICODE et
> donc la conversion est nécessaire...
>

Cette conversion n'est elle pas implicite, notamment lors de l'appel


aux
API ?

Il me semble que c'est lorsque qu'une API renvoie une chaîne Unicode
qu'il faut faire une conversion explicite.

Il y a peut être aussi la manière de déclarer les paramètres de l'API
qui a son importance :

As Any

ou

As String



Heloo Jacques,

Après quelques essais, le meiux est effectivement de modifier
la décalration de copyMemory, comme ceci:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(pDst As Any, pSrc As String, ByVal ByteLen As Long)

et l'appel comme cela:
CopyMemory t(0), ByVal StrPtr(s), l

La conversion explicite fonctionne aussi, en laissant pSrc as Any:

CopyMemory tba(0), ByVal StrPtr((StrConv(s, vbFromUnicode))), sizeTba


La première méthode est ultra rapide (<0.6 milisecondes), la seconde
reste très correcte, même si elle est 15 fois plus lente (9 milli)

Bref, par rapport à mes 36 millisecondes, c'est PARFAIT !


Un grand merci à toi et à François, je peux laisser mon Visual C++ de
coté pour cette fois :-)

--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ;
Avatar
Jean-Marc
"Picalausa François" a écrit dans le message de
news:
"Jacques93" a écrit dans le message de news:

> En faisant :
>
> Private Declare Sub CopyMemory Lib "kernel32" Alias


"RtlMoveMemory" _
> (Destination As Any, _
> Source As Any, _
> ByVal Length As Long)
>
> Function CvrtStr2ByteArray(ByRef s As String, _
> ByVal szt As Long, _
> ByRef t() As Byte) As Boolean
> CopyMemory t(0), ByVal s, szt
>
> CvrtStr2ByteArray = True
> End Function
>

Hello,

On peut aussi le faire sans API, puisque VB supporte un cast


implicite:
Dim byBytes() As Byte
Dim strString As String

strString = "Hello World"
'<mauvaise foi>Note: tu vois qu'il faut un StrConv? Hein


Hein?</mauvaise
foi> ;-)
'N'empêche que si jamais je choppe celui qui a enlevé une heure


cette
nuit...!
byBytes = StrConv(strString, vbFromUnicode)

Dim i As Long

For i = 0 To UBound(byBytes)
Debug.Print Chr$(byBytes(i));
Next i

Par contre, Jean-Marc, pourrait-on (si tu as le temps de le faire)


avoir les
bench des différentes méthodes exposées? Je suis sur ce coup ci très


curieux
des résultats et de ce qui les départage...
A priori, le StrConv (ou le passage vers une API qui entraine le même
mécanisme) est particulièrement lent. (le mappage d'une safearray sur


une
string premettant éventuellement de travailler avec des entiers -


VT_I2 - et
des chrw$ et autres fonctions unicode devrait donc être le plus


rapide)

Bref, curieux je suis...



Hello,

Je vais donc faire des tests cet après-midi, et je fournirais les
résultats ce soir!

<yoda>la curiosité est bonne, François, cet état d'esprit garder tu
dois!</yoda>

--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ;
Avatar
Picalausa François
"Jacques93" a écrit dans le message de news:

En faisant :

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)

Function CvrtStr2ByteArray(ByRef s As String, _
ByVal szt As Long, _
ByRef t() As Byte) As Boolean
CopyMemory t(0), ByVal s, szt

CvrtStr2ByteArray = True
End Function




Hello,

On peut aussi le faire sans API, puisque VB supporte un cast implicite:
Dim byBytes() As Byte
Dim strString As String

strString = "Hello World"
'<mauvaise foi>Note: tu vois qu'il faut un StrConv? Hein Hein?</mauvaise
foi> ;-)
'N'empêche que si jamais je choppe celui qui a enlevé une heure cette
nuit...!
byBytes = StrConv(strString, vbFromUnicode)

Dim i As Long

For i = 0 To UBound(byBytes)
Debug.Print Chr$(byBytes(i));
Next i

Par contre, Jean-Marc, pourrait-on (si tu as le temps de le faire) avoir les
bench des différentes méthodes exposées? Je suis sur ce coup ci très curieux
des résultats et de ce qui les départage...
A priori, le StrConv (ou le passage vers une API qui entraine le même
mécanisme) est particulièrement lent. (le mappage d'une safearray sur une
string premettant éventuellement de travailler avec des entiers - VT_I2 - et
des chrw$ et autres fonctions unicode devrait donc être le plus rapide)

Bref, curieux je suis...

--
Picalausa François
Avatar
Jean-Marc
> "Picalausa François" a écrit dans le message de
news:
> Hello,
>
> Il y a une technique très efficace qui consiste à mapper un


SAFEARRAY
sur ta
> string...
> Ceci évite de devoir allouer deux fois la mémoire (donc gain de


temps)
et de
> devoir recopier la chaine à chaque modification (ou d'effectuer les
> modification en double) puisqu'on travaille sur la même zone
mémoire...




Hello François,


J'ai un souci avec le MapSafeArray; ça ne fonctionne pas car il mappe
la chaine en unicode:

' ma fonction
for k=0 to 32:debug.print tb2(k); " ";:next k
65 66 67 68 69 32 70 71 72

' un simple copymemory
for k=0 to 32:debug.print tb3(k); " ";:next k
65 66 67 68 69 32 70 71 72

' ==>> ICI AVEC MAP SAFEARRAY
for k=0 to 32:debug.print tb1(k); " ";:next k
65 0 66 0 67 0 68 0 69 0

Et si j'appelle MapSafeArrrayToString avec un
strconv explicite (pas d'intérêt, juste pour tester) et
bien alors ca ne marche pas non plus. Je trouve 4 premiers
bytes tout à fait déconnant, puis la suite est bonne.

Bizarre ....

Sinon, j'ai fini le reste du benchmark.

--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ;
Avatar
Picalausa François
Hello,

Jean-Marc, ayant quelques problèmes avec mon newsreader, je ne vois ton
message qu'a travers google groups qui ne fonctionne pas pour répondre à
cause d'autres problèmes techniques... Donc je répondrai à côté du post ;-)

Quand tu utilise StrConv, c'est normal que la chaine mappée ne corresponde à
rien:
Dim Blah As String
'Blah existe
Blah = "Hello World"
MaFonction(StrConv(Blah, ...))
'Ici, la conversion n'existe déjà plus

Par contre,
Blah = StrConv("...", ...)
MaFonction(Blah, ...)
Fonctionne

Pour le banch, voici une méthode entièrement UNICODE donc plus rapide (à
condition de changement le traitement à postériori pour travailler en
UNICODE):
Option Explicit

Private Const FADF_HAVEVARTYPE = &H80
Private Const VT_I2 = 2
Private Const VT_UI1 = 17

Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type

Private Type SAFEARRAY
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
End Type

Private Declare Function VarPtrArray _
Lib "msvbvm60.dll" _
Alias "VarPtr" _
( _
Var() As Any _
) _
As Long
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" _
( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)

Private opsa As Long 'pointeur vers la safearray précédente
Private opvdata As Long 'pointeur vers les données précédentes
Private osb As SAFEARRAYBOUND 'bornes précédentes du tableau

Private Function MapSafeArrrayToString(psa As Long, strText As String) As
Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
MapSafeArrrayToString = False

'Vérifie la validité des données en entrée
If ((StrPtr(strText) <> 0) And (psa <> 0)) Then
'Vérifie qu'on a bien démappé précédemment
If (opsa = 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal psa, LenB(sa))

'Demande une array typée en 1D non lockée
If ((sa.fFeatures And FADF_HAVEVARTYPE) And (sa.cDims = 1) And
(sa.cLocks = 0)) Then
'Demande de plus que cette array soit typée As Byte ou As
Integer
CopyMemory vt, ByVal (psa - 4), LenB(vt)
If (vt = VT_UI1) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa), LenB(osb))

'Remap le tableau
sab.cElements = LenB(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab, LenB(sab))

sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))

MapSafeArrrayToString = True
ElseIf (vt = VT_I2) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa), LenB(osb))

'Remap le tableau
sab.cElements = Len(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab, LenB(sab))

sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))

MapSafeArrrayToString = True
End If
End If
End If
End If
End Function

Private Function UnmapSafeArray() As Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
UnmapSafeArray = False

'Vérifie la validité des données en entrée
If (opsa <> 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal opsa, LenB(sa))

'Restaure les données
Call CopyMemory(ByVal opsa + LenB(sa), osb, LenB(osb))
sa.pvData = opvdata
Call CopyMemory(ByVal opsa, sa, LenB(sa))

'Oublie tout de ce qui s'est passé
opsa = 0
opvdata = 0
osb.cElements = 0
osb.lLbound = 0
End If
End Function

Private Function GetPsa(PPSA As Long) As Long
Call CopyMemory(GetPsa, ByVal PPSA, LenB(GetPsa))
End Function

Private Sub Form_Load()
Dim Blah As String
Dim byBlah() As Integer
Dim i As Long

ReDim byBlah(0)

Blah = "Hello World!"

'ATTENTION : jusqu'à UnmapSafeArray, il est préférable que
'Blah ne sorte jamais du scope
If MapSafeArrrayToString(GetPsa(VarPtrArray(byBlah)), Blah) Then
For i = LBound(byBlah) To UBound(byBlah)
Debug.Print ChrW$(byBlah(i));
Next i

UnmapSafeArray
End If
End Sub

Le problème est donc plus de retirer le temps de conversion pour chaque
appel (faire à l'avance le StrConv, stoquer le résultat et utiliser des
StrPtr pour le copymemory) pour effectivement comparer les méthodes et pas
la conversion en background... enfin, je crois ;-)

--
Picalausa François
Avatar
Jean-Marc
Hello François,

Ok, j'ai bien compris. Je vois maintenant que de fait, il faut modifier
le
traitement à posteriori.
Evidemment, ca ne m'arrange pas ici car mon table de bytes() est destiné
à
être utilisé tel quel. SI je dois rajouter du post-traitement, je vais
perdre
le bénéfice gagné.

Par contre, dans un autre contexte d'utilisation (tout en Unicode),
c'est clair
que le mappage en SafeArray est hyper rapide (je le ferais apparaitre
dans les
résultats du bench).


--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ;


"Picalausa François" a écrit dans le message de
news:%
Hello,

Jean-Marc, ayant quelques problèmes avec mon newsreader, je ne vois


ton
message qu'a travers google groups qui ne fonctionne pas pour répondre


à
cause d'autres problèmes techniques... Donc je répondrai à côté du


post ;-)

Quand tu utilise StrConv, c'est normal que la chaine mappée ne


corresponde à
rien:
Dim Blah As String
'Blah existe
Blah = "Hello World"
MaFonction(StrConv(Blah, ...))
'Ici, la conversion n'existe déjà plus

Par contre,
Blah = StrConv("...", ...)
MaFonction(Blah, ...)
Fonctionne

Pour le banch, voici une méthode entièrement UNICODE donc plus rapide



condition de changement le traitement à postériori pour travailler en
UNICODE):
Option Explicit

Private Const FADF_HAVEVARTYPE = &H80
Private Const VT_I2 = 2
Private Const VT_UI1 = 17

Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type

Private Type SAFEARRAY
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
End Type

Private Declare Function VarPtrArray _
Lib "msvbvm60.dll" _
Alias "VarPtr" _
( _
Var() As Any _
) _
As Long
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" _
( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)

Private opsa As Long 'pointeur vers la safearray précédente
Private opvdata As Long 'pointeur vers les données précédentes
Private osb As SAFEARRAYBOUND 'bornes précédentes du tableau

Private Function MapSafeArrrayToString(psa As Long, strText As String)


As
Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
MapSafeArrrayToString = False

'Vérifie la validité des données en entrée
If ((StrPtr(strText) <> 0) And (psa <> 0)) Then
'Vérifie qu'on a bien démappé précédemment
If (opsa = 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal psa, LenB(sa))

'Demande une array typée en 1D non lockée
If ((sa.fFeatures And FADF_HAVEVARTYPE) And (sa.cDims = 1)


And
(sa.cLocks = 0)) Then
'Demande de plus que cette array soit typée As Byte ou


As
Integer
CopyMemory vt, ByVal (psa - 4), LenB(vt)
If (vt = VT_UI1) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),


LenB(osb))

'Remap le tableau
sab.cElements = LenB(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,


LenB(sab))

sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))

MapSafeArrrayToString = True
ElseIf (vt = VT_I2) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),


LenB(osb))

'Remap le tableau
sab.cElements = Len(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,


LenB(sab))

sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))

MapSafeArrrayToString = True
End If
End If
End If
End If
End Function

Private Function UnmapSafeArray() As Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
UnmapSafeArray = False

'Vérifie la validité des données en entrée
If (opsa <> 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal opsa, LenB(sa))

'Restaure les données
Call CopyMemory(ByVal opsa + LenB(sa), osb, LenB(osb))
sa.pvData = opvdata
Call CopyMemory(ByVal opsa, sa, LenB(sa))

'Oublie tout de ce qui s'est passé
opsa = 0
opvdata = 0
osb.cElements = 0
osb.lLbound = 0
End If
End Function

Private Function GetPsa(PPSA As Long) As Long
Call CopyMemory(GetPsa, ByVal PPSA, LenB(GetPsa))
End Function

Private Sub Form_Load()
Dim Blah As String
Dim byBlah() As Integer
Dim i As Long

ReDim byBlah(0)

Blah = "Hello World!"

'ATTENTION : jusqu'à UnmapSafeArray, il est préférable que
'Blah ne sorte jamais du scope
If MapSafeArrrayToString(GetPsa(VarPtrArray(byBlah)), Blah) Then
For i = LBound(byBlah) To UBound(byBlah)
Debug.Print ChrW$(byBlah(i));
Next i

UnmapSafeArray
End If
End Sub

Le problème est donc plus de retirer le temps de conversion pour


chaque
appel (faire à l'avance le StrConv, stoquer le résultat et utiliser


des
StrPtr pour le copymemory) pour effectivement comparer les méthodes et


pas
la conversion en background... enfin, je crois ;-)

--
Picalausa François




Avatar
Jacques93
Bonjour,
Jean-Marc a écrit :
Bonjour chers collègues,

j'ai un besoin précis d'optimisation: Je dois convertir
une chaine en un table de Bytes.



[...]

Comme le fait remarquer François Picalausa, il semblerait que certains
messages se soient "perdus" (dès hier, donc avant l'heure "fantôme" de
cette nuit), 12 messages sur ce fil dans OE, TB et MN alors que dans
Google Groups, il y en a 19.

Désolé si je n'ai pas répondu, ou répondu à côté ...

--
Cordialement,

Jacques.
1 2