I want to pass a byte[]
to a method takes a IntPtr
Parameter in C#, is that possible and how?
-
Could you provide more details? Why would you want to do it? – Grzenio Feb 11 '09 at 16:32
-
2You need this if you use DirectShow API for example... to get data from VideoRenderer, you have to use this... and `GCHandle` method works like a charm... also the `fixed` method. :P :)) – Cipi Mar 11 '11 at 09:45
-
You need this for anything that is transferring terrabytes of data and you want to avoid the extra copy. Use your imagination. – Brain2000 Jan 04 '19 at 15:14
-
Here is how to do it with span without unsafe [Get pointer (IntPtr) from a Span
staying in safe mode](https://stackoverflow.com/a/75362556/3351489) – CorrM Feb 06 '23 at 14:27
7 Answers
Another way,
GCHandle pinnedArray = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
// Do your stuff...
pinnedArray.Free();
-
1@Cipi Per one of Eric Lipperts other post, this should have the Fixed keyword instead of using the GC – makerofthings7 Dec 17 '12 at 21:59
-
thanks a lot. Work nice and its pretty easy. I am not so skilled in GCHandles and Marshal. Can someone say me what pluses have the Marshal and what the GCHandle and where use which one? Thanks – tomdelahaba May 08 '13 at 03:42
-
1
-
3@piggy: I think the disadvantage of Marshal is that you have to make a copy of your data (which can take a long time and waste memory you might need) – Riki Aug 26 '13 at 06:10
-
6@makerofthings7 I do not believe Lippert is saying to use 'fixed' instead of the GC [to pin objects], I believe he is saying do not use the GC to pin an object indefinitely, along with saying do not use fixed to do the same, either. – Cameron Feb 20 '15 at 01:21
The following should work but must be used within an unsafe
context:
byte[] buffer = new byte[255];
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
// Do your stuff here
}
Beware: you have to use the pointer within the fixed
block. The GC can move the object once you are no longer within the fixed
block.

- 56
- 8

- 2,095
- 1
- 12
- 13
-
19I like this answer because it doesn't involve allocating extra memory just to access the data – Xcalibur Apr 07 '11 at 04:02
-
3This is the best answer if large byte[] are used. A copy has too much overhead – makerofthings7 Dec 17 '12 at 22:02
-
This then leaves me with "Unable to read memory" on the byte[]. Is there a go to solution for this? – Jody Sowald Jan 20 '21 at 16:17
Not sure about getting an IntPtr to an array, but you can copy the data for use with unmanaged code by using Mashal.Copy:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);
Alternatively you could declare a struct with one property and then use Marshal.PtrToStructure, but that would still require allocating unmanaged memory.
Edit: Also, as Tyalis pointed out, you can also use fixed if unsafe code is an option for you

- 83,269
- 19
- 178
- 237
-
Just to clarify, `Marshal.Copy` with that overload needs a start index. The call should be `Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);` – mkenyon May 20 '10 at 16:26
-
better to get IntPtr without creating new memory, like @user65157's answer. – Lin Apr 20 '18 at 03:30
-
I had to copy my managed memory to unmanaged memory to get the unmanaged code to execute correctly. – James Westgate Apr 08 '21 at 12:19
You could use Marshal.UnsafeAddrOfPinnedArrayElement
to get a memory pointer to the array (or to a specific element in the array). Keep in mind that the array must be pinned first as per the API documentation:
The array must be pinned using a GCHandle before it is passed to this method. For maximum performance, this method does not validate the array passed to it; this can result in unexpected behavior.

- 56
- 8

- 201
- 2
- 2
-
2This is - I think - the only way to get an IntPtr for an array element which is not the 0th (without using unsafe code). – Guido Domenici Jul 11 '11 at 15:54
-
5To make this code reliable array should be pinned first http://msdn.microsoft.com/en-us/library/3k4y07x3.aspx – sergtk Jun 23 '13 at 12:49
Here's a twist on @user65157's answer (+1 for that, BTW):
I created an IDisposable wrapper for the pinned object:
class AutoPinner : IDisposable
{
GCHandle _pinnedArray;
public AutoPinner(Object obj)
{
_pinnedArray = GCHandle.Alloc(obj, GCHandleType.Pinned);
}
public static implicit operator IntPtr(AutoPinner ap)
{
return ap._pinnedArray.AddrOfPinnedObject();
}
public void Dispose()
{
_pinnedArray.Free();
}
}
then use it like thusly:
using (AutoPinner ap = new AutoPinner(MyManagedObject))
{
UnmanagedIntPtr = ap; // Use the operator to retrieve the IntPtr
//do your stuff
}
I found this to be a nice way of not forgetting to call Free() :)

- 3,511
- 3
- 29
- 34
-
4You may want to investigate deriving your AutoPinner from SafeHandle since that class takes concurrency and security "gotchas" into account, as well as encouraging/using the recommended IDisposable pattern. – kkahl Dec 06 '16 at 02:03
Marshal.Copy works but is rather slow. Faster is to copy the bytes in a for loop. Even faster is to cast the byte array to a ulong array, copy as much ulong as fits in the byte array, then copy the possible remaining 7 bytes (the trail that is not 8 bytes aligned). Fastest is to pin the byte array in a fixed statement as proposed above in Tyalis' answer.

- 1,064
- 12
- 14
In some cases you can use an Int32 type (or Int64) in case of the IntPtr. If you can, another useful class is BitConverter. For what you want you could use BitConverter.ToInt32 for example.

- 1,211
- 1
- 9
- 13
-
19**You should never, ever use Int32 or Int64 in place of a pointer**. If you have to port your code to a different platform (32-bit->64-bit), you'll have all kinds of headaches. – xxbbcc Nov 07 '12 at 20:00
-
5No, there's no valid case in which you can correctly and safely use an `Int32` as a pointer. This was a bad practice done years ago and it lead to all kinds of porting issues. Even an `Int64` isn't safe because there are already 128-bit architectures and pointer size will increase. Pointers should only ever be represented as pointers. – xxbbcc Nov 08 '12 at 15:04
-
1I used it in .NET CF projects without issues, of course you'd have problems if you try to port it to other systems, but there is code out there not meant to be ever ported. – Alejandro Mezcua Nov 09 '12 at 10:18
-
It's true that some code is not planned to be ported but things can change pretty quickly. Even if your usage on the CF was justified (I don't know) it's still bad advice to a generic question. The only valid scenario for using `int` / `long` for pointers is when the language used has no concept of them (for example VB6). C# supports pointers and has `IntPtr` - there's no need at all to use an `int` in place of a pointer ever. I'll remove my -1 if you add clear warnings and an explanation of potential issues to your answer. – xxbbcc Nov 09 '12 at 15:04
-
-
In .NET CF for example there weren't all the options for marshalling data that the full framework has, and that option offered a simple option, though to be fair now it doesn't really matter much anymore unless you develop for rugged devices, as that platform is dead; but this is a 2009 question. – Alejandro Mezcua Nov 09 '12 at 17:15
-
3Well, you _are_ comparing the usage of very specific marshalling code to this general question about using pointers in C#. In normal C# there's no scenario where this would be valid. I know it's an old question but I voted it down because I came across it by looking for the way to allocate memory for an IntPtr - others will see this, too. I see your advice as very dangerous because people will go with it thinking they got away with solving a problem easily when all they got is future trouble. – xxbbcc Nov 09 '12 at 19:19