Posted on 2011-09-16
Last Modified: 2012-06-27
I need to use Marshal.Copy function but I'm not sure about how to do that.
Now I try this :

Dim MyData(255) As Byte
Do data (MyData)  from ComPort

Marshal.Copy(BufferAddress, MyData, ind, 256)

Is it right or this can give some problems when ind will be too big?
How can i read ByteArray(255)  from data i have in Marshal?

Question by:mastiSoft
  • 4
  • 3
LVL 15

Expert Comment

ID: 36553179
You can allocate not managed memory using Marshal.AllocHGlobal.
This returns a IntPtr object (memory Pointer)

It is not safe use aritmetic with IntPtr.

You can Copy From and To your allocated memory using Marshall.Copy.
This allows copy from Managed memory to allocated an also from Allocated to managed.
Managed memory can be an Byte array and also any Blitable class or Structure.

Note that you need also Fee allocated memory (Marshall.FreeHGlobal).

You must take care about Memory Bounds as you can write on any memory with invalid length or invalid IntPtr.
This can cause unpredictable errors.

Author Comment

ID: 36553293
Your answer still doesn't open my mind. If I can't use arithmetic IntPtr how should I do .
The data flow in my computer and I have to save it somewhere to be able read back that amount of data I need . I can't believe that the only way to do that is create temporary binary file and manipulate data with FileGet,FilePut functions. if it so then VB net really big sh..  :-(((
LVL 15

Expert Comment

ID: 36553904
Note that IntPtr allows Convert to Int32 and Int64, you can add and substract offset, then create an new IntPtr from result.

But... Note that your program can run on 32 and 64 bits and conversions can become incorrect as correct IntPtr is unsigned integer and accepted conversion on .Net is from Signed integer.

Most times the original Intptr correspond to a Positive number and result from add an Offset is a Positive number, but you can´nt grants this is allways correct as a computer can manage 4gb memory and from 2gb limit correspond to negative numbers.

Note that Xp limit the memory from a Process to 2Gb, But this do´nt grants IntPtr is Positive number.

Note that Interop creates an releases not managed memory and you call not managed methods with interop.
Using Interop automatic mechanism, you avoid risks.

Here a sample where I allocate memory to do custom interop.
In this code, I Declare some vars as IntPtr on LzmaCompress and LzmaUncompress, then I need allocate memory and do Marsall.copy.

I can also declare it as Byte()  (Byte Array). Then Interop do all Work.
This opition is most Safe, But at this case, I manage a lot of memory (some Mb) and do´nt want allocate unnecesary managed memory and copy empty array (all zeros) to unmanaged memory ...

Declare Function LzmaCompress Lib "LZMA.dll" Alias "LzmaCompress" ( _
      ByVal dest As IntPtr, ByRef destLen As Int32, _
      ByVal src As IntPtr, ByVal srcLen As Int32, _
      ByVal outProps As IntPtr, ByRef outPropsSize As Int32, _
      ByVal level As Int32, _
      ByVal dictSize As Int32, ByVal lc As Int32, ByVal lp As Int32, _
      ByVal pb As Int32, ByVal fb As Int32, ByVal numThreads As Int32) As Int32

    Declare Function LzmaUncompress Lib "LZMA.dll" Alias "LzmaUncompress" ( _
       ByVal dest As IntPtr, ByRef destLen As Int32, _
       ByVal src As IntPtr, ByRef srcLen As Int32, _
       ByVal props As IntPtr, ByVal propsSize As Int32) As Int32

      Private Shared ReadOnly outProps As IntPtr = Marshal.AllocHGlobal(5)

      Public Function DeCode() As MemoryStream
          Dim Bytes() As Byte = Nothing
          If _CLength > 0 Then
             Dim il = Content.Length - 5, PtrIn = Marshal.AllocHGlobal(il)
             Marshal.Copy(Content, 0, outProps, 5)
             Marshal.Copy(Content, 5, PtrIn, il)

             Dim ol = _Length, out = Marshal.AllocHGlobal(ol)
             If LzmaUncompress(out, ol, PtrIn, il, outProps, 5) = 0 AndAlso ol = _Length Then
                  Bytes = New Byte(ol - 1) {}
                  Marshal.Copy(out, Bytes, 0, ol)
             End If
             If Bytes Is Nothing Then Throw New Exception("Error Descompresión")
             Bytes = Content
          End If
          Return New MemoryStream(Bytes) ', 0, Bytes.Length, True, True)
      End Function

      Public Sub EnCode(ByVal msIn As MemoryStream)
          _Length = CInt(msIn.Length)
          If _Length < 256 OrElse (Prj IsNot Nothing AndAlso Prj.Compress = False) Then
              Content = msIn.ToArray
              _CLength = 0
              Dim liBf = CInt(msIn.Length), iBf = Marshal.AllocHGlobal(liBf)
              Marshal.Copy(msIn.GetBuffer, 0, iBf, liBf)

              Dim lOBf = liBf - 5, OBf = Marshal.AllocHGlobal(lOBf)
              Dim loutProps = 5 'Valor máximo de OutPropos length

              Dim dsize = 1 << 19, mode = 5 'Tamaño diccionario, Modo - defecto=5, 4->Fast
              If liBf > dsize Then dsize = 1 << 20 : mode = 4
              Dim res = LzmaCompress(OBf, lOBf, iBf, liBf, outProps, loutProps, mode, dsize, -1, -1, -1, -1, -1)

              If res = 0 Then
                 Content = New Byte(lOBf + loutProps - 1) {}
                 Marshal.Copy(outProps, Content, 0, 5)
                 Marshal.Copy(OBf, Content, 5, lOBf)
                _CLength = Content.Length
                 Content = msIn.ToArray 'Tamaño comprimido sería mayor que original
                 _CLength = 0
              End If
          End If
          _Fecha = CType(Date.Now.Ticks \ TimeSpan.TicksPerMinute, Int32)
          Dirty = True
          version = PrjVers
          If Prj IsNot Nothing Then Prj.Dirty = True
      End Sub

Open in new window

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.


Author Comment

ID: 36554417
Thank you for answer. I try to understand  your code. You have 2 functions here and many undeclared variables. I can't see where you get data from memory (back after saving it in Marshal).
LVL 15

Expert Comment

ID: 36554672
Encode do a Lzma compress of Msin (memory Stream) and stores result on Content member.
Decode do a lzma decompress Content member and returns a memorystream.

I change  outProps  definition:

    Private Shared ReadOnly outProps(4) As Byte
     ByVal outProps As Byte(), ByRef outPropsSize As Int32, _
     ByVal props As Byte(), ByVal propsSize As Int32) As Int32
               Array.Copy(Content, outProps, 5)
               Array.Copy(outProps, Content, 5)

Now Interop allocates memory and release it for OutProps when I call LzmaCompress and LzmaUncompress.
Note that this var only has 5 bytes. Performance is not afected.

LVL 15

Accepted Solution

x77 earned 500 total points
ID: 36554687
About Lzma compression:

Is a Opensource Project:
There are a version that works as managed DLL (lzma#), but I use the c++ version.

Author Closing Comment

ID: 36554861
Thank you very much and have a nice weekend.

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Windows 10 is here and for most admins this means frustration and challenges getting that first working Windows 10 image. As in my previous sysprep articles, I've put together a simple help guide to get you through this process. The aim is to achiev…
I use more than 1 computer in my office for various reasons. Multiple keyboards and mice take up more than just extra space, they make working a little more complicated. Using one mouse and keyboard for all of my computers makes life easier. This co…
This is a video describing the growing solar energy use in Utah. This is a topic that greatly interests me and so I decided to produce a video about it.
A company’s greatest vulnerability is their email. CEO fraud, ransomware and spear phishing attacks are the no1 threat to a company’s security. Cybercrime is responsible for the largest loss of money to companies today with losses projected to r…

911 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now