Click here to Skip to main content
15,885,537 members
Articles / Programming Languages / Visual Basic
Article

Equivalent of CopyMemory in .NET

Rate me:
Please Sign up or sign in to vote.
3.16/5 (31 votes)
24 Oct 20043 min read 171.1K   33   11
This tutorial will show you how to use the corresponding managed classes in .NET framework to get the same result as unmanaged Windows API function CopyMemory (RtlMoveMemory) provides.

Introduction

This tutorial will show you how to use the corresponding managed classes in .NET framework to get the same result as unmanaged Windows API function CopyMemory (RtlMoveMemory) provides. The equivalent classes I am going to describe are System.Runtime.InteropServices.Marshal and System.Buffer.

I will first give a little introduction to both these classes (Marshal and Buffer), and then take examples of CopyMemory from VB 6 code and explain corresponding classes and code in Visual Basic .NET 2003 to achieve the same effect on data types such as integers, bytes, strings, arrays and structures. For good performance, install Service Pack 1 for .NET framework 1.1. I also compile all mentioned code with SP1. You can obtain it from Microsoft.

Explanation

CopyMemory copies block of memory to a different block of memory without regard to the data type that is stored there. This results in an ultra fast copy of data. VB 6 declaration is as follows:

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

But in .NET, most usage of CopyMemory is inappropriate and will not work properly. You need to use the corresponding managed class to do the same job such as System.Runtime.InteropServices.Marshal or System.Buffer.

System.Runtime.InteropServices.Marshal

This class provides a collection of methods for allocating unmanaged memory, copying unmanaged memory blocks, and converting managed to unmanaged types, as well as other miscellaneous methods used when interacting with unmanaged code to bridge between the managed and unmanaged programming models. I will show you VB.NET's amazing new power over memory and pointers. That power is found in three new tools: IntPtr, .NET's platform-dependent representation of a memory address; GCHandle, which helps you pin and retrieve the address of data in the managed memory heap; the Marshal class, the one-stop shop for all your memory allocation, cleanup, and manipulation needs. For more detail about its members, see MSDN latest release.

System.Buffer

Manipulates arrays of primitive types such as Boolean, Char, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Single, and Double, and does not apply to objects. Each primitive type is treated as a series of bytes without regard to any behavior or limitation associated with the primitive type. It has very useful members to manipulate arrays. For more detail about its members, see MSDN latest release.

Array to other data types or vice versa

Let us consider VB 6 code to copy data from byte array to integer variable.

VB
Dim Longvalue As Long, Str As String
Str = "Adnan Samuel"
Dim ByteArray () As Byte
'Convert string to byte and copy to byte array
ByteArray = StrConv(Str, vbFromUnicode)
'copy entire array to variable Longvalue
CopyMemory Longvalue, ByteArray (0), 4
'Print it in immediate window
Debug.print LongValue

Equivalent VB.NET code

VB
Imports System.Runtime.InteropServices
Imports System.Text
Dim LongValue As Integer
Dim Str As String = "Adnan Samuel"
'A byte array
Dim ByteArray () As Byte
'Convert string to byte and copy to byte array
ByteArray = Encoding.Default.GetBytes(Str)
'Create Gchandle instance and pin variable required
Dim MyGC As GCHandle = GCHandle.Alloc(LongValue, GCHandleType.Pinned)
'get address of variable in pointer variable
Dim AddofLongValue As IntPtr = MyGC.AddrOfPinnedObject()
'Use copy method to copy array data to variable’s 
'address with length specified(4)
Marshal.Copy(ByteArray, 0, AddofLongValue, 4)
'First read value of variable from its address 
'in memory in order to use it
LongValue = Marshal.ReadInt32(AddofLongValue)
'Print to output window
Debug.WriteLine("Vlaue of LongValue is: " & LongValue)
'Free GChandle to avoid memory leaks
MyGC.Free()

Now reverse of it (integer to byte array) is very easy, just a small change in Marshal.Copy method, that is:

VB
'VB 6 code
CopyMemory ByteArray(0), Longvalue, 4

Equivalent VB.NET code will be, change in Copy method requires source as Intptr, destination array, index of destination array to start copy, and number of bytes to copy.

VB
Marshal.Copy (AddofLongValue, ByteArray, 0, 4)
'Rest of code same

That’s all.

Strings

Let us consider a VB 6 code to copy string.

VB
'Source string to copy from
Dim Source as String
''Destination string to copy
Dim  Dest as String
Source="Adnan"
'Leave 5 spaces for Source string to copy before 
'Dest string to show  output as AdnanSamuel
Dest="    Samuel"
'Copy source string in beginning of Dest string
CopyMemory StrPtr(Dest), StrPtr(Source),10
'Show output as AdnanSamuel
Msgbox Dest

Equivalent VB.NET code

However, you have equivalent of StrPtr() function in VB.NET (that is by creating instance of GCHANDLE and pinning a variable and then obtain its address as we did earlier). After that, you can even use unmanaged CopyMemory function in VB.NET to do the same job. But I recommend that you should not do that since it is not .NET way. Instead, you should use very fast and powerful classes like String and StringBuilder and other String functions such as MID and StrConv() etc. to achieve the same effect.

Let us consider VB.NET code to achieve the same effect mentioned above:

VB
'Source string to copy from
Dim Source As String = "Adnan"
'Destination string to copy
Dim Dest As String = "Samuel"
'Copy source string in beginning of Dest string
Dest = Dest.Insert(0, Source)
'Show output as AdnanSamuel
Console.WriteLine(Dest)

Array to another Array

Let us consider VB 6 code for copying byte array to integer array.

VB
Dim ByteArray() As Byte, Str As String
Dim IntArr(0 To 3) As Integer, i As Integer
Str = "Adnan Samuel"
ByteArray = StrConv(Str, vbFromUnicode)
'Copy entire byte array to integer array of specified length (8)
CopyMemory IntArr(0), ByteArray(0), 8
'Print to immediate window
For i = 0 To 3
 Debug.Print IntArr(i)
Next

Equivalent VB.NET code

VB
Imports System.Buffer
Imports System.Text
Dim Str As String = "Adnan Samuel"
Dim MyBytesString() As Byte, i As Integer
Dim int(3) As short ‘inter array
'Convert string to byte and copy to byte array
MyBytesString = Encoding.Default.GetBytes(Str)
'Use BlockCopy method to copy block of bytes array
'to integer array of specified length (8)
Buffer.BlockCopy(MyBytesString, 0, int, 0, 8)
'Print to output window
For i = 0 To 3
 Debug.WriteLine(int(i))
Next

Again reverse is as easy, just change source array with destination array and rest of the code remains same.

Structures (user-defined type)

Let us copy data from byte array to Types (structures) in VB 6.

VB
'Declare Type
Private Type Test
  Var1 As Integer
  Var2 As Integer
End Type
 Dim Str As String, i As Integer
Dim ByteArray () As Byte
' Declare Type variable to store its value
Dim Tst As Test
Str = "Adnan Samuel"
'Convert to string to bytes
ByteArray = StrConv(Str, vbFromUnicode)
'Copy entire byte array to Type of specified length (4)
CopyMemory Tst, ByteArray (0), 4
' use them ready to use print them
Debug.Print Tst.Var1
Debug.Print Tst.Var2

Equivalent VB.NET code

VB
Imports System.Runtime.InteropServices
Imports System.Text
'In .NET Types are changed to Structures
Private Structure Test
   Dim Var1 As Short
   Dim Var2 As Short
 End Structure
' Function to Create structure must be called first
Private Function BulidStr(ByVal Buff() As Byte, _
      ByVal MyType As System.Type) As Object
  Dim MyGC As GCHandle = GCHandle.Alloc(Buff, GCHandleType.Pinned)
 'Marshals data from an unmanaged block of memory to a newly
'allocated managed object of the specified type.
  Dim Obj As Object = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, MyType)
  Return Obj
 'Free GChandle to avoid memory leaks
  MyGC.Free()
 End Function
'Start here
 Dim Str As String = "Adnan Samuel"
 Dim Tst As Test ‘ Stuctuer variable
 Dim ByteArray () As Byte, i As Int16
'convert to bytes
  ByteArray = Encoding.Default.GetBytes(Str)
 'Call BulidStr method to create structure 
 'and copy byte array data to structure
 Tst = BulidStr(ByteArray, Tst.GetType)
 'Now use it and print it
 Debug.WriteLine(Tst.Var1.ToString)
 Debug.WriteLine(Tst.Var2.ToString)

Conclusion

I am always willing to help, so if you have any questions, suggestions about my article, feel free to email me. You can also reach me on MSN Messenger with screen name “Maxima”.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Pakistan Pakistan
I am software engineer and working from last four years in the information technology field. I love to do intresting tasks. I love to see diffrent places and listening muzik.

Comments and Discussions

 
QuestionMy Vote of 5 Pin
manonthecorner_31-Dec-19 11:56
manonthecorner_31-Dec-19 11:56 
QuestionMy vote of 5 Pin
dl4gbe10-Oct-11 11:31
dl4gbe10-Oct-11 11:31 
GeneralCopying Structure to String Pin
Nimbus200110-Apr-08 6:07
Nimbus200110-Apr-08 6:07 
I read through your article, it is well illustrated example of using Marshal class, However can you shed more light on using them to copy Structures into Strings?

Thanks,
Raghu.
GeneralDatarow to byte array Pin
Sanket Joshi16-Nov-07 20:54
Sanket Joshi16-Nov-07 20:54 
GeneralNew to unmanaged code Need Marshalling help Pin
jdperk10-Aug-07 12:09
jdperk10-Aug-07 12:09 
Generalgreat, there is a way to send string through windows message Pin
Tomzhu24-Jul-07 17:15
Tomzhu24-Jul-07 17:15 
GeneralStructure needs unmanaged type - try this. Pin
David Woods12-Dec-06 17:23
David Woods12-Dec-06 17:23 
QuestionVery nice code [modified] Pin
La Wi6-Aug-06 9:13
La Wi6-Aug-06 9:13 
AnswerRe: Very nice code Pin
La Wi6-Aug-06 9:40
La Wi6-Aug-06 9:40 
AnswerRe: Very nice code Pin
David Woods12-Dec-06 17:21
David Woods12-Dec-06 17:21 
GeneralGreat Article Pin
Leonardo T.1-Aug-06 12:29
Leonardo T.1-Aug-06 12:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.