Jump to content
  • Advertisement
Sign in to follow this  
squashed_bug

[.net] byte [] to an IntPtr

This topic is 3664 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 style

int* 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)

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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();

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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();
}

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!