Let's say we have this function
Function MakeDWORD(Value As Long) As String
Dim Result As String * 4
CopyMemory ByVal Result, Value, 4
MakeDWORD = Result
End Function
Could someone help me with a clear step-by-step explanation of what CopyMemory does? I hate using code I dont completely understand.
That function converts the given value into a signed(not sure if it's signed) long and returns it.
Yes, but if this function had to be recoded w/o using copymemory, what would it look like?
Quote from: FrostWraith on August 22, 2006, 09:03 PM
Yes, but if this function had to be recoded w/o using copymemory, what would it look like?
As far as I know, CopyMemory is the only way you can convert between VB6 values and C structs.
Quote from: Topaz on August 22, 2006, 09:53 PM
As far as I know, CopyMemory is the only way you can convert between VB6 values and C structs.
Not at all.
Quote from: FrostWraith on August 22, 2006, 05:32 PM
Could someone help me with a clear step-by-step explanation of what CopyMemory does? I hate using code I dont completely understand.
CopyMemory does exactly what it looks like it's doing. It copies memory from one location to another. However, in this case, it's being used to create a string value from a long integer. Because if you used Visual Basic's CStr function (Convert to String), you'd end up with this:
Dim myNum as Long
Dim myStr as String
myNum = 12345678
myStr = CStr(myNum) ' myStr = "12345678"
When you use CopyMemory on the other hand, the long value (4 bytes on most systems), is copied into the string. So if we look at 12345678 in hex, it's equal to 0x00BC614E (or rather, in memory, it's going to be stored as 0x4E61BC00 because of the endian-ness of the PC.) Thus, the string after CopyMemory holds the character 0x4E, 0x61, 0xBC, and 0x00. This is significantly different from the original string.
Now, for the purpose: Visual Basic doesn't have pointers (generally speaking) and type-casting on a low level, so when we're sending binary data (technically, all data is binary, but the term seems to be used for data that contains non-printable characters) we have to convert it into a string format. There's a huge difference between sending the string "2" (0x32) and the number 2 (0x02000000). What CopyMemory allows us to do is load that binary data into a string in an easy fashion. And you can see it in MakeDWORD where an input long integer is converted to a four byte string.
Lastly, if you wanted to write a replacement, it would look something like this:
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, _
source As Any, ByVal bytes As Long)
Private Sub Form_Load()
Debug.Print DebugOutput(MakeDWORDVB(12345678))
Debug.Print DebugOutput(MakeDWORDCopyMemory(12345678))
End Sub
Public Function MakeDWORDVB(Value As Long) As String
Dim tempStr As String
' Convert the value to its hexadecimal representation.
' In the case of 12345678, this is "BC614E"
tempStr = CStr(Hex(Value))
' Pad the string with zeros.
' Use the Right$ function to remove all but the last 8
' characters. This is because a 4-byte value needs 8
' representative bytes. In the case of 12345678, these
' bytes are "00BC614E".
tempStr = Right$("00000000" & tempStr, 8)
' Now, because of the endianness of the PC (has to do with
' byte order), we have to reverse the bytes for the DWORD
' to be read appropriately. This little loop takes care
' of converting each set of two bytes ("00" "BC" "61" "4E")
' to their character format. It also reverses the byte
' order so that the DWORD will be read appropriately by the
' receiving end.
Dim i As Byte
For i = 1 To 7 Step 2
MakeDWORDVB = Chr$("&H" & Mid$(tempStr, i, 2)) & MakeDWORDVB
Next i
End Function
Function MakeDWORDCopyMemory(Value As Long) As String
Dim Result As String * 4
CopyMemory ByVal Result, Value, 4
MakeDWORDCopyMemory = Result
End Function
Output:
0000: 4E 61 BC 00 Na¼.............
0000: 4E 61 BC 00 Na¼.............
Why were you born? Show off! :P
I don't much feel like reading TehUsers long overcomplicated explanation, so I'll explain it simply:
Function MakeDWORD(Value As Long) As String
Dim Result As String * 4
CopyMemory ByVal Result, Value, 4
MakeDWORD = Result
End Function
This takes a 4byte DWORD and converts it to a 4 byte string. There are no conversion operators for visual basic that work on this level.
Copymemory works by moving a section/block of memory from one location to another Src to Dest
In this case Src is Value, Dest is Result.
Src = Long, Dest = String
Thus offering effecient conversion from Long To String (CStr does literal conversion to an ascii string)
Note, CopyMemory doesn't convert anything. It's given three values, in, out, and length. It copys, byte for byte, length bytes worth of in to the pointer specified in out. We just happen to use that to write the contents of a Long to a String. If you ask me, that behavior shouldn't be used in good programming practice, because that doesn't sound like the intended use.
Excuse my Java/C#/whatever you call this, but this is what is, by my standards, a proper makeDword(int) function. Untested, of course, but you'll live (seriously, you will!):
public String makeDword(int i)
{
byte b0 = (byte)(i && 0xff000000) >> 24;
byte b1 = (byte)(i && 0x00ff0000) >> 16;
byte b2 = (byte)(i && 0x0000ff00) >> 8;
byte b3 = (byte)(i && 0x000000ff);
return b0.toString() + b1.toString() + b2.toSring() + b3.toString();
}
Yeah, don't call that C#.
Ah, quit insulting my coding styles and teach me the proper! I took a Java class and have those coding standards fixed in my brain now, so eh.
Yea thats was to hard looking to be C#, C# is all about doing it easy.
Quote from: Joex86] link=topic=15573.msg157187#msg157187 date=1156480629]
Ah, quit insulting my coding styles and teach me the proper! I took a Java class and have those coding standards fixed in my brain now, so eh.
If you wanted to make it hex, you'd just call:
i.ToString("x8");
The 8 is included to ensure that it's 8 characters wide (with 0s prepended). To skip that, just "x" will do.
Plus your code would have failed because you attempted to do the logical AND (&&) when the numerical AND was desired.
Plus it would have failed because you typecasted the result of the AND to (byte), and then shifted it, when you should have shifted the AND result and then typecasted. Proper:
(byte)((i & 0xff000000) >> 24);
Plus your example would have printed out the number big-endian. Not necessarily wrong (it's how we write individual numbers in hex), I'm just saying.
Note that Strings are not adequate nor proper places to store binary data in either Java or C# because they are subject to encoding strategies related to their runtime environments. The CopyMemory function is used to store data in Strings in Visual Basic because people don't use byte arrays for it. Byte arrays are, however, available in Java and C#.
[code]copy memory is really usefull, especially for filling vb types which can be build alot like cstructs
double = 8bytes
long = 4bytes
integer = 2bytes
byte = 1byte
to answer your question, without copymem that function looks like
function long2str(byval n as long) as string
long2str = _
chr((n and &HFF000000&) mod 256) & _
chr((n and &H00FF0000&) mod 256) & _
chr((n and &H0000FF00&) mod 256) & _
chr(n and &H000000FF&)
end function[/code]
or backwards... dont know offhand, too lazy for testing!
It seems kind of pointless to use a function like that to convert between each other when you could just use pointers and mov operations? I mean I'm sure pointers would be far more effecient and easier to read than using a bunch of binary operators to do it. but then again joe is a complete newbie++ the vb6 users used copymemory because vb6 doesn't support pointers... and joes code also sucks because it only applys to dword->string conversion... what happens if you need support for bigger types/arrays... seems like a lot more overhead than required but as I said before joe is a completely dumb newbie++
Quote from: FrostWraith on August 22, 2006, 09:03 PM
Yes, but if this function had to be recoded w/o using copymemory, what would it look like?
Function Makedword(Value as long) as string
if value >= 0 then
makedword = makedword & chr(value mod 256) & chr((value mod (256^2)) \ (256^1)) & chr((value mod (256^3)) \ (256^2)) & chr((value mod (256^4)) \ (256^3))
else
value=value + 2147483648#
makedword = makedword & chr(value mod 256) & chr((value mod (256^2)) \ (256^1)) & chr((value mod (256^3)) \ (256^2)) & chr(((value mod (256^4)) \ (256^3))+128)
end if
End Function
notice they are backward slashes (\), which mean integer division, not normal division
if its not the above, then add Makedword=strreverse(makedword) right below the "End if"
Quote from: Ante on February 14, 2007, 10:08 AM
Quote from: FrostWraith on August 22, 2006, 09:03 PM
Yes, but if this function had to be recoded w/o using copymemory, what would it look like?
Function Makedword(Value as long) as string
if value >= 0 then
makedword = makedword & chr(value mod 256) & chr((value mod (256^2)) \ (256^1)) & chr((value mod (256^3)) \ (256^2)) & chr((value mod (256^4)) \ (256^3))
else
value=value + 2147483648#
makedword = makedword & chr(value mod 256) & chr((value mod (256^2)) \ (256^1)) & chr((value mod (256^3)) \ (256^2)) & chr(((value mod (256^4)) \ (256^3))+128)
end if
End Function
notice they are backward slashes (\), which mean integer division, not normal division
if its not the above, then add Makedword=strreverse(makedword) right below the "End if"
OH DEAR GOD THAT HURT, lol.
Function MakeDWORD(Value as Long) As String
Dim RET as String * 4
Mid(RET, 1, 1) = Value And &HFF000000
Mid(RET, 2, 1) = Value And &HFF0000
Mid(RET, 3, 1) = Value And &HFF00
Mid(RET, 4, 1) = Value And &HFF
MakeDWORD = RET
End Function
Note that you're doing three bad things:
1. Using return as a variable.
2. Concatenating to a string that has no contents.
3. Modifying a value passed to the function with out intention of making a ByRef return.
I don't even know what that whole if is about. :P
Function MakeDWORD(Value as Long) As String
Dim RET as String * 4
Mid(RET, 1, 1) = Value And &HFF000000
Mid(RET, 2, 1) = Value And &HFF0000
Mid(RET, 3, 1) = Value And &HFF00
Mid(RET, 4, 1) = Value And &HFF
MakeDWORD = RET
End Function
that's setting values of longs into chars. for example, if the value is &H11111111, the first line will read Mid(RET, 1, 1) = &H11000000. at least add chr to convert it to string. make sure to shift it over several places
FYI, neither one of those functions work.
Frozen's will also overflow at random for no reason btw, can tell you this without even testing it.
You should never use a straight out value of 256 in that manor.
Quote from: l2k-Shadow on February 17, 2007, 09:17 AM
FYI, neither one of those functions work.
does mine work if u add Makedword=strreverse(makedword) at the end of the function?
Quote from: Ante on February 18, 2007, 11:24 AM
Quote from: l2k-Shadow on February 17, 2007, 09:17 AM
FYI, neither one of those functions work.
does mine work if u add Makedword=strreverse(makedword) at the end of the function?
lol... no it overflows on the first statement you can see it from the code.
Oh yeah.. add Chr() to mine.
I'm so used to byte[] now. :P
Quote from: Joex86] link=topic=15573.msg165117#msg165117 date=1171830197]
Oh yeah.. add Chr() to mine.
I'm so used to byte[] now. :P
No that won't work either, you are forgetting that all variables in VB except char are signed. You'd have to do something like this to overcome that barrier (this won't work in all cases such as VB will think that &HFFFF = &HFFFFFFFF because both produce same result, -1.. therefore you'd have to have multiple functions recognizing each one, so if you must not use RtlMoveMemory, you'd best go with the Chr$(eachbyte of the DWORD) function as postead earlier):
Function MakeDWORD(Value As Long) As String
Dim Outbuf As String, nLng As Long
Outbuf = Chr$((Value And &HFF))
nLng = (((Value And &HFF00) \ (2 ^ 8)) Mod 256)
If nLng < 0 Then nLng = (nLng + 256)
Outbuf = Outbuf & Chr$(nLng)
nLng = (((Value And &HFF0000) \ (2 ^ 16)) Mod 256)
If nLng < 0 Then nLng = (nLng + 256)
Outbuf = Outbuf & Chr$(nLng)
nLng = (((Value And &HFF000000) \ (2 ^ 24)) Mod 256)
If nLng < 0 Then nLng = (nLng + 256)
Outbuf = Outbuf & Chr$(nLng)
MakeDWORD = Outbuf
End Function
Quote from: l2k-Shadow on February 18, 2007, 01:36 PM
Quote from: Ante on February 18, 2007, 11:24 AM
Quote from: l2k-Shadow on February 17, 2007, 09:17 AM
FYI, neither one of those functions work.
does mine work if u add Makedword=strreverse(makedword) at the end of the function?
lol... no it overflows on the first statement you can see it from the code.
did u mean the if value >= 0 then line? cuz theres no place for that to overflow
i can't imagine which other line it could overflow from...every chr() has a value within it that is positive and less than 256
and the negative values are bumped into positive with that line, and put back into "negative" with the last char
Quote from: Ante on February 18, 2007, 08:24 PM
Quote from: l2k-Shadow on February 18, 2007, 01:36 PM
Quote from: Ante on February 18, 2007, 11:24 AM
Quote from: l2k-Shadow on February 17, 2007, 09:17 AM
FYI, neither one of those functions work.
does mine work if u add Makedword=strreverse(makedword) at the end of the function?
lol... no it overflows on the first statement you can see it from the code.
did u mean the if value >= 0 then line? cuz theres no place for that to overflow
i can't imagine which other line it could overflow from...every chr() has a value within it that is positive and less than 256
and the negative values are bumped into positive with that line, and put back into "negative" with the last char
no i mean the statement after value >=0 line. it's because VB does math operations using long variables.. and (256 ^ 4) is &HFFFFFFFF which is an unsigned long, however since longs in VB are signed, overflow occurs.
hm...
u coulda jus doen this then
Function Makedword(Value as long) as string
if value >= 0 then
makedword = makedword & chr(value mod 256) & chr((value mod (256^2)) \ (256^1)) & chr((value mod (256^3)) \ (256^2)) & chr(value \ (256^3)
else
value=value + 2147483648#
makedword = makedword & chr(value mod 256) & chr((value mod (256^2)) \ (256^1)) & chr((value mod (256^3)) \ (256^2)) & chr((value \ (256^3))+128)
end if
End Function
Quote from: A2 on February 12, 2007, 09:06 PM
[code]copy memory is really usefull, especially for filling vb types which can be build alot like cstructs
double = 8bytes
long = 4bytes
integer = 2bytes
byte = 1byte
to answer your question, without copymem that function looks like
function long2str(byval n as long) as string
long2str = _
chr((n and &HFF000000&) mod 256) & _
chr((n and &H00FF0000&) mod 256) & _
chr((n and &H0000FF00&) mod 256) & _
chr(n and &H000000FF&)
end function[/code]
or backwards... dont know offhand, too lazy for testing!
omg this post was more then 3 months old when you replied to it. jeez.
Quote from: Ante on February 19, 2007, 09:40 AM
hm...
u coulda jus doen this then
Function Makedword(Value as long) as string
if value >= 0 then
makedword = makedword & chr(value mod 256) & chr((value mod (256^2)) \ (256^1)) & chr((value mod (256^3)) \ (256^2)) & chr(value \ (256^3)
else
value=value + 2147483648#
makedword = makedword & chr(value mod 256) & chr((value mod (256^2)) \ (256^1)) & chr((value mod (256^3)) \ (256^2)) & chr((value \ (256^3))+128)
end if
End Function
Then your function produces the same result as any MakeDWORD VB function.. you get the -1 problem where &HFFFF = &HFFFFFFFF and produces ÿÿÿÿ if you input &HFFFF or &HFFFFFFFF... :'(