API - CopyMemory

G

Guest

I am trying to use CopyMemory to copy arrays as follows:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal
pDst As Long, ByVal pSrc As Long, ByVal ByteLen As Integer)

dim kin(11) as Integer
dim kout(11) as Integer

kin(1)= 1 'set values for two elements to see if Kout is the same
kin(5) = 5

CopyMemory(kout(0), kin(0), 48)

It compiles and runs but all I get in Kout is "0" for all elements.
 
A

Al Reid

Dennis said:
I am trying to use CopyMemory to copy arrays as follows:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal
pDst As Long, ByVal pSrc As Long, ByVal ByteLen As Integer)

dim kin(11) as Integer
dim kout(11) as Integer

kin(1)= 1 'set values for two elements to see if Kout is the same
kin(5) = 5

CopyMemory(kout(0), kin(0), 48)

It compiles and runs but all I get in Kout is "0" for all elements.

Try changing Long to Integer in the API declare. Looks like a VB6
declaration. VB6 Long = VB.Net Integer
 
G

Guest

Tried that, no change. I found an example on the web that timed the various
methods of copying arrays, i.e., for loop, assignment, and CopyMemory written
for vb.net. It doesn't work either as it only copies zeros. The author
apparently didn't test it by actually putting values in the source array.
 
J

Jack Russell

Dennis said:
Tried that, no change. I found an example on the web that timed the various
methods of copying arrays, i.e., for loop, assignment, and CopyMemory written
for vb.net. It doesn't work either as it only copies zeros. The author
apparently didn't test it by actually putting values in the source array.
I would have the that you should be passing by ref not by val but ....
 
H

Herfried K. Wagner [MVP]

Dennis said:
CopyMemory(kout(0), kin(0), 48)

It compiles and runs but all I get in Kout is "0" for all elements.

I am curious why you would want to use 'CopyMemory'. You may want to use
'Buffer.BlockCopy' instead, which is pretty fast.
 
D

Dragon

Dennis,

First, pDst and pSrc should be declared as ByRef. They are pointers, and
passing pointers ByVal doesn't make much sense.
Second, their type must match the type of an array.

So, your declatation should look like:

~
Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
ByRef Destination As Integer, _
ByRef Source As Integer, _
ByVal Length As Integer _
)
~

Third, you can declare them as arrays, so it will be:

~
Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
<MarshalAs(UnmanagedType.LPArray)> ByVal Destination() As
Integer, _
<MarshalAs(UnmanagedType.LPArray)> ByVal Source() As Integer, _
ByVal Length As Integer _
)
~

Fourth, why don't you use the Array.Copy method?

Roman
 
G

Guest

Thanks for the corrections to my code. You are absolutely correct in that I
need byRef. However, on the type in the declaration of CopyMemory, when
passed by reference, isn't an integer or long passed to the Com routine as
the address? For example, if my array is of type byte and I pass the array
by reference, what is actually passed...isn't it a 4 byte address?

As for using Array.CopyTo, in the end, I actually will be using CopyMemory
to copy a structure into an array for use with another com object.
 
G

Guest

Thanks, you are correct in that I should be using byref. I was trying code
from an example I got from the net (it didn't work either) and that's why.
 
G

Guest

Thanks Herfried but in the end, I want to copy a structure into an array
contained in another array for passing to another com object. That's why I
didn't use Buffer class.
 
D

Dragon

Dennis said:
Thanks for the corrections to my code. You are absolutely correct in that I
need byRef. However, on the type in the declaration of CopyMemory, when
passed by reference, isn't an integer or long passed to the Com routine as
the address? For example, if my array is of type byte and I pass the array
by reference, what is actually passed...isn't it a 4 byte address?

First, CopyMemory isn't a COM routine. 8=]

Yes, passing ByRef means passing IntPtr (platform-dependent integer)
value which represents address of a variable, so if you wanted to
specify an address (ByVal), you should declare it as IntPtr. But when
you declare parameter ByRef you specify a type of variable itself, not
type of pointer to it, don't you?

If you pass an array by reference you get garbage 8=]. You can either
pass its first element by reference, or pass the whole array by value.
You will get the same result though.
As for using Array.CopyTo, in the end, I actually will be using CopyMemory
to copy a structure into an array for use with another com object.

You can use Marshal.StructureToPtr() method for this, for example:

~
Dim a(Marshal.SizeOf(GetType(Decimal)) - 1) As Byte
Marshal.StructureToPtr(23568.23573D,
Marshal.UnsafeAddrOfPinnedArrayElement(a, 0), False)
Stop
~

Roman
 
J

Jay B. Harlow [MVP - Outlook]

Dennis,
Rather then risk memory, or at least to minimize, memory corruption.

I would recommend using Buffer.BlockCopy to copy arrays (as you initially
asked).

Alternatively I would use Marshal.Copy, Marshal.PtrToStructure,
Marshal.StructureToPtr and possible other methods on the
System.Runtime.InteropServices.Marshal class to marshal from the Managed to
Unmanaged world.

I would not attempt to implement my own marshaller with CopyMemory as the
..NET Framework team has already done the work for me...

--
Hope this helps
Jay
T.S. Bradley - http://www.tsbradley.net


|I am trying to use CopyMemory to copy arrays as follows:
|
| Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal
| pDst As Long, ByVal pSrc As Long, ByVal ByteLen As Integer)
|
| dim kin(11) as Integer
| dim kout(11) as Integer
|
| kin(1)= 1 'set values for two elements to see if Kout is the same
| kin(5) = 5
|
| CopyMemory(kout(0), kin(0), 48)
|
| It compiles and runs but all I get in Kout is "0" for all elements.
|
| --
| Dennis in Houston
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top