PInvoke - Pinning byte arrays

  • Thread starter Thread starter _iycrd
  • Start date Start date
I

_iycrd

After numerous problems, I'm having second thoughts about using
C++/CLI to wrap a native DLL. On the other hand, PInvoke seems like
it will take a huge amount of work, if it will work at all.

The native DLL uses raw data buffers that are normally handed to it
(via pointer) from another native function. If I'm piloting this with
C#/PInvoke, how could those raw data buffers be created and
immobilized? In C++/CLI, there is pin_ptr to keep the CLR's memory
manager from moving things, but I don't see how this can be done in
C#/PInvoke. Can it?
 
Native memory buffers don't need to be pinned, they are not a subject of the
GC.

Willy.

| After numerous problems, I'm having second thoughts about using
| C++/CLI to wrap a native DLL. On the other hand, PInvoke seems like
| it will take a huge amount of work, if it will work at all.
|
| The native DLL uses raw data buffers that are normally handed to it
| (via pointer) from another native function. If I'm piloting this with
| C#/PInvoke, how could those raw data buffers be created and
| immobilized? In C++/CLI, there is pin_ptr to keep the CLR's memory
| manager from moving things, but I don't see how this can be done in
| C#/PInvoke. Can it?
|
 
Hi,

I'm not exactlu sure I understand your question correctly. Maybe Willy
already answered your question, but just in case if you want to pin a object
in the managed heap so the GC won't move it arround you need to create a
GCHandle to it of type Pinned such as

GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);

To unpin the object use GCHandle.Free method.

GCHandles can be converted to and from IntPtr for using with PInvoke.

Keep in mind that pinning objects in managed heap can undermine GC
efficiency.
 
If you declare the API correctly the framework will marshal data types
for you and ensure that they are either copied or pinned. In the case
of blittable types (a byte array is blittable) they are pinned during
marshaling.

Consider the following DllImport declarations.

[DllImport("kernel32.dll")]
public static extern void CopyMemory(IntPtr dst, IntPtr src, long
length);

or

[DllImport("kernel32.dll")]
public static extern void CopyMemory(byte[] dst, byte[] src, long
length);

You can make both declarations work, but in the first example you would
have to obtain a pointer to your buffer and the pin/unpin it manually.
If you declare the API similar to the second example then the marshaler
will do all of this for you.

Brian
 
| On Thu, 9 Mar 2006 14:13:22 +0100, "Willy Denoyette [MVP]"
|
| >Native memory buffers don't need to be pinned, they are not a subject of
the
| >GC.
| >
| >Willy.
|
| Hi Willy,
|
| Does C# have provision for creating native buffers?
|

If you mean buffers in the process heap instead of the GC heap, look at the
Marshal class, there are a number of methods (AllocHGloba, AllocCoTaskMem)
that do just that.

Willy.
 
Back
Top