How to get IntPtr from byte[] in C#
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
How to convert byte[] array to IntPtr?
You can use an Encoding.GetString()
to convert the bytes to a string. Which encoding to use depends on the encoding of the string, e.g. Encoding.UTF8.GetString(pointer_arrays, 0) for UTF8 encoding, Encoding.Unicode for unicode, Encoding.ASCII for ASCII or Encoding.Default for the default code page of your system.
C# how to get Byte[] from IntPtr
Have you looked into Marshal.Copy?
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.copy.aspx
How to cast IntPtr to byte*
You can simply write:
byte* ptr = (byte*)int_ptr;
You don't have to use the fixed keyword. You don't want to pin the IntPtr, do you?
Can IntPtr be cast into a byte array without doing a Marshal.Copy?
As others have mentioned, there is no way you can store the data in a managed byte[]
without copying (with the current structure you've provided*). However, if you don't actually need it to be in a managed buffer, you can use unsafe
operations to work directly with the unmanaged memory. It really depends what you need to do with it.
All byte[]
and other reference types are managed by the CLR Garbage Collector, and this is what is responsible for allocation of memory and deallocation when it is no longer used. The memory pointed to by the return of GetBuffer
is a block of unmanaged memory allocated by the C++ code and (memory layout / implementation details aside) is essentially completely separate to your GC managed memory. Therefore, if you want to use a GC managed CLR type (byte[]
) to contain all the data currently held within your unmanaged memory pointed to by your IntPtr
, it needs to be moved (copied) into memory that the GC knows about. This can be done by Marshal.Copy
or by a custom method using unsafe
code or pinvoke or what have you.
However, it depends what you want to do with it. You've mentioned it's video data. If you want to apply some transform or filter to the data, you can probably do it directly on the unmanaged buffer. If you want to save the buffer to disk, you can probably do it directly on the unmanaged buffer.
On the topic of length, there is no way to know the length of an unmanaged memory buffer unless the function that allocated the buffer also tells you what the length is. This can be done in lots of ways, as commenters have mentioned (first field of the structure, out paramtere on the method).
*Finally, if you have control of the C++ code it might be possible to modify it so that it is not responsible for allocating the buffer it writes the data to, and instead is provided with a pointer to a preallocated buffer. You could then create a managed byte[]
in C#, preallocated to the size required by your C++ code, and use the GCHandle
type to pin it and provide the pointer to your C++ code.
How to copy data pointed by byte* to a buffer pointed by IntPtr? (C#)
I don't believe there is a framework method that will work. Marshal.Copy can copy memory into and out of an IntPtr
buffer, but it doesn't work with pointers.
Instead you can P/Invoke the native MoveMemory function which copies memory between two pointers.
[DllImport("Kernel32.dll", EntryPoint="RtlMoveMemory", SetLastError=false)]
static extern void MoveMemory(IntPtr dest, IntPtr src, UIntPtr size);
...
byte* imgData; // image data
uint uiDataSize; // image size
...
IntPtr ptr;
buffer.GetPointer(out ptr);
MoveMemory(ptr, (IntPtr)imgData, (UIntPtr)uiDataSize);
Yes the size
parameter of MoveMemory
is UIntPtr
not an int
because the SIZE_T
used in the native code is 32 bits on 32 bit systems and 64 bits on 64 bit systems.
IntPtr to Byte Array and Back
The exception thrown by the call to SizeOf
is correct; the method has no way of knowing what the length of the array that you are passing to it is, it just has a pointer.
To that end, the easiest way to get the data is to call the static Copy
method on the Marshal class, passing the pointer to the unmanaged data, the index and number of bytes to read, as well as a pre-allocated buffer of bytes to marshal the data into.
As for getting the size of the array, as Anton Tykhyy pointed out in the comments, it appears (be very careful here) that the call to Twain.GlobalLock(hImage)
is using memory allocated by GlobalAlloc
, which means that you can make a call to the GlobalSize
API function through the P/Invoke layer to get the size.
If it is not a handle to something allocated by a call to GlobalAlloc
then you need to find out how the Twain
module is allocating the memory and use the appropriate mechanism to determine the length of the memory pointed to by the IntPtr
.
Related Topics
A Simple C# Dll - How to Call It from Excel, Access, Vba, Vb6
How to Format a Number into a String with Leading Zeros
Linq Select Distinct with Anonymous Types
How to Build a Datatemplate in C# Code
Why Should I Use Int Instead of a Byte or Short in C#
Listen to Changes of Dependency Property
Capture Screenshot Including Semitransparent Windows in .Net
Servicestack Rest API and Cors
How to Loop Through Ienumerable in Batches
What Is the Equivalent of Memset in C#
Convert JSON String to JSON Object C#
Read Post Data Submitted to ASP.NET Form
Can a C# Class Inherit Attributes from Its Interface
"Invalid JSON Primitive" in Ajax Processing
Correct, Idiomatic Way to Use Custom Editor Templates with Ienumerable Models in ASP.NET MVC