[.net] byte [] to an IntPtr

Started by
23 comments, last by Fiddler 15 years, 7 months ago
Help converting a byte [] into an IntPtr?
Advertisement
Im assuiming you want to convert a byte ptr into an int ptr?
Because they are both ptrs, just either use a C-style cast or
C++ reinterpret_cast:
byte ptr[]; // our pointer...int* pInt = (int*)ptr; // C styleint* pInt2 = reinterpret_cast<int*> (ptr); // C++

Note that integers are 32bits in size (on 32bit systems),
so incrementing pInt by 1 will jump 4 elements in the byte array.

Hope this helps!

(I dont use .NET, but am assuming the same still applies)
Use the following method:
public static IntPtr UnsafeAddrOfPinnedArrayElement (
Array arr,
int index
)
Gets the address of the element at the specified index inside the specified array.

arr: The Array containing the desired element.
index: The index in the arr parameter of the desired element.

MSDN Link
Assuming you are using C#, I believe the best way is as follows,

using the System.Runtime.InteropServices.Marshal class:

byte[] data = ...;IntPtr ptr = Marshal.AllocHGlobal(data.Length);try{  Marshal.Copy(data,0,ptr,data.Length);  //deal with ptr}finally{  Marshal.FreeHGlobal(ptr);}



There are very few cases where you need to use unsafe code. This is not one of them. This is far, far safer (not that pointers are safe at all). It is also debatable if it's actually any slower.


UnsafeAddrOfPinnedArrayElement is dangerous as the address in memory of the array may well change at any time. It is intended for use with pinned memory in C++/Cli (as is my understanding) It also does *not* validate the input is pinned. Apparently you can pin memory in C# using GCHandle, but I haven't done this before, so I don't know how safe it is - and importantly I can't see how you pin an Array, not an IntPtr. So in summary I don't think it's a safe option.

GCHandle gch = GCHandle.FromIntPtr(ptr);..gch.Free();
and another

byte[] byteArray;
fixed (byte *_bp = byteArray)
{
somethingorother((IntPtr)_bp);
}
As the great Washu tells us, only resort to unsafe code if you are absolutely certain the technique is not possible without it (which is highly unlikely). The performance hit from using unsafe code is HUGE. Check out his journal or blog for more info.

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

For large arrays you should not copy elements around. In this case, if you do not want to resort to unsafe code, use the following snippet:
            GCHandle h0 = GCHandle.Alloc(array, GCHandleType.Pinned);            try            {                // h0.AddrOfPinnedObject() will get you your IntPtr            }            finally            {                h0.Free();            }

[OpenTK: C# OpenGL 4.4, OpenGL ES 3.0 and OpenAL 1.1. Now with Linux/KMS support!]

Quote:Original post by Fiddler
For large arrays you should not copy elements around. In this case, if you do not want to resort to unsafe code, use the following snippet:
            GCHandle h0 = GCHandle.Alloc(array, GCHandleType.Pinned);            try            {                // h0.AddrOfPinnedObject() will get you your IntPtr            }            finally            {                h0.Free();            }


Awesome. Where/how did you find/figure this out? [smile]

This is by far the best way, and safe provided you don't buffer overrun I guess
Quote:Original post by capn_midnight
The performance hit from using unsafe code is HUGE.


I'm pretty sure that this isn't correct. I've spent a substantial amount of time researching this subject, and I've found that there is no performance penalty for unsafe code per se in C#.

There is a very slight penalty to using the 'fixed' keyword which is often associated with unsafe because the runtime pins the array, but even that usually isn't bad unless used in an inner loop (normally you'd use 'fixed' outside of a loop).

Just to prove my point, take the following code:

        static unsafe int test1(int* ptr, int index)        {            return ptr[index];        }        static int test2(int[] array, int index)        {            return array[index];        }        static void Main(string[] args)        {            int[] foo = new int[1024];            unsafe            {                fixed (int* bar = &foo[0])                {                    test1(bar,0);                }            }            test2(foo,0);        }


Now, lets take a look the machine code that test1() generates

            return ptr[index];00000028  mov         eax,dword ptr [edi+esi*4] 0000002b  mov         ebx,eax 


and test2()

            return array[index];00000028  cmp         edi,dword ptr [esi+4] 0000002b  jb          00000032 0000002d  call        79333451 00000032  mov         eax,dword ptr [esi+edi*4+8] 00000036  mov         ebx,eax 


Clearly, using the unsafe pointer is faster, because there is no null reference check - which is obvious as the first three instructions of test2().

There is a penalty to using the 'fixed' keyword, which includes a null reference check and the pointer is pinned, but clearly if you were going to iterate over all of the elements in the array using the unsafe pointer would be substantially faster.

[Edited by - krum on April 11, 2007 9:57:10 AM]
I can confirm that math code that's optimized with unsafe code is much faster.

This topic is closed to new replies.

Advertisement