19

I have an unsafe byte* pointing to a native byte array of known length. How can I convert it to byte[]?

An unsafe sbyte* pointing to a zero-terminated native string can be converted to a C# string easily, because there is a conversion constructor for this purpose, but I can't find a simple way to convert byte* to byte[].

kol
  • 27,881
  • 12
  • 83
  • 120
  • shouldn'y `byte[]` be `const byte*` by default? so try indexing the pointer as `*(myByte+index);` But i guess it if were that easy you wouldn't be asking.... – Shark Jul 10 '13 at 11:27
  • You should be able to write `*(myByte+index)` as `myByte[index]`. No conversion necessary. – H H Jul 10 '13 at 11:29
  • @HenkHolterman I must convert it to byte[] because I have to pass it to the constructor of IPAddress. – kol Jul 10 '13 at 11:33
  • But do you need safe (managed) `byte[]` or not? – H H Jul 10 '13 at 11:34
  • @HenkHolterman The IPAddress ctor needs a safe/managed byte[]: http://msdn.microsoft.com/en-us/library/t4k07yby.aspx – kol Jul 10 '13 at 11:37

2 Answers2

24

If ptr is your unsafe pointer, and the array has length len, you can use Marshal.Copy like this:

byte[] arr = new byte[len];
Marshal.Copy((IntPtr)ptr, arr, 0, len);

But I do wonder how you came by an unsafe pointer to native memory. Do you really need unsafe here, or can you solve the problem by using IntPtr instead of an unsafe pointer? And if so then there's probably no need for unsafe code at all.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • This looks good, I was gonna suggest traversing the pointed-to array and filling by hand, or memcpy, but this seems like a C# way of doing it. (y) – Shark Jul 10 '13 at 11:34
  • This question is a follow-up to this one: http://stackoverflow.com/questions/17549123/c-sharp-performance-using-unsafe-pointers-instead-of-intptr-and-marshal – kol Jul 10 '13 at 11:45
  • I'd err towards `IntPtr` and `Marshal.Copy` if I were you. – David Heffernan Jul 10 '13 at 11:47
  • Thank you, David, I didn't know that an unsafe pointer can be casted to IntPtr. – kol Jul 10 '13 at 11:51
  • "I'd err towards IntPtr and Marshal.Copy if I were you." - Why? I would also like to know your opinion on my other question (pls. check out the link if you have time). I haven't got any answers to that one, just some comments. – kol Jul 10 '13 at 11:55
  • Well, in the scenario in this question, where you need a managed byte[], then there's really no need for unsafe. At the other question, you can use unsafe to avoid taking a copy of the native memory. If there's a performance gain by avoiding that copy that is significant, then unsafe becomes an option. Otherwise I'd always prefer not to use unsafe code. – David Heffernan Jul 10 '13 at 12:01
  • Can I do the above without new (which may be lot of memory consuming) - just reference to the same memory? – Eitan Jan 22 '19 at 20:09
  • @Eitan yes, using `Span` – David Heffernan Jan 22 '19 at 20:34
  • How can I do this without marshal.copy? I used unsafe code to get the byte array without using marshal copy to begin with, for performance reasons. Now I need to use marshalcopy anyways?? – savram Oct 29 '21 at 17:36
  • @savram ask a new question, because this questions asks something different from what you ask – David Heffernan Oct 29 '21 at 18:49
1

The Marshal class could help you.

byte[] bytes = new byte[length];
for(int i = 0; i < length; ++i)
  bytes[i] = Marshal.ReadByte(yourPtr, i);

I think you might use Marshal.Copy too.

dotixx
  • 1,490
  • 12
  • 23
  • 4
    Since this has to happen in an unsafe block, you don't need `Marshal.ReadByte` and you can just use good old fashioned pointer de-reference and pointer increment. That is if you wish to perform the copy in a loop rather than using `Marshal.Copy`. – David Heffernan Jul 10 '13 at 11:34