PInvoke, marshalling pointer to array

G

Guest

Hi people

I am wrapping a C dll using PInvoke from C#. I need to wrap the following signature in C

int dma_start( const UCHAR* data, UINT data_length )

The function should start with a DMA operation, and I have to use it from my C# program. I am really unsure what type of marshalling I should use.

The data parameter is a pointer to an array of byte data. This data must not be copied when calling the function. Plus, the .NET framework should not move the data around in memory until the method returns. Currently, I've made the interop signature as follows

[DllImport("UsedLib.dll", EntryPoint="dma_start")
[return : MarshalAs(UnmanagedType.I4)
public static extern bool DMAStart (
[MarshalAs(UnmanagedType.U1)] ref byte DMAData
[MarshalAs(UnmanagedType.U4)] uint DMALength
)

Is this a good way to define the pointer to the array (DMAData)
How do I say to the .NET framework that it shouldn't move the byte data around in memory, until the method returns

Thanks a lot
 
N

n!

The function should start with a DMA operation, and I have to use it from
my C# program. I am really unsure what type of marshalling I should use.
The data parameter is a pointer to an array of byte data. This data must
not be copied when calling the function. Plus, the .NET framework should not
move the data around in memory until the method returns. Currently, I've
made the interop signature as follows:
[DllImport("UsedLib.dll", EntryPoint="dma_start")]
[return : MarshalAs(UnmanagedType.I4)]
public static extern bool DMAStart (
[MarshalAs(UnmanagedType.U1)] ref byte DMAData,
[MarshalAs(UnmanagedType.U4)] uint DMALength
);

Is this a good way to define the pointer to the array (DMAData)?
How do I say to the .NET framework that it shouldn't move the byte data
around in memory, until the method returns?

When I last exported an array to unmanaged code I used the GCHandle class
inside System.Runtime.InteropServices:

For more complete sample, I have a project on GotDotNet which is a wrapper
around the OpenExr graphics library (still in development). If you search on
http://www.gotdotnet.com for the SharpExr workspace, there is some code that
exports an array to unmanaged code inside the 'InternalReadPixels' method
(within the IO\ExrReader.cs file). Sorry I haven't got a direct link, out
http web connection here is broken and I can't look up the web address at
the moment. Failing that, there's an older code drop at
http://www.btinternet.com/~nfactorial/managed/exrdotnet/exrdotnet.zip but
I'm not sure how old that code is compared to the one on gotdotnet.

It basically looks like:

using System.Runtime.Interop;

private void InternalReadPixels( Rgba[] pixels, int start, int end )
{
if ( disposed )
throw new ObjectDisposedException( ... );

if ( null == pixles )
throw new ArgumentNullException( ... );

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

SomeImportedFunction( handle.AddrOfPinnedObject() );

handle.Free();
}

Note, the final free refers to the pinning of the object rather than the
actual data.

n!
 
B

BMermuys

Hi,

You can also declare it as :
public extern int dma_start ( byte[] data, uint data_length );

An array of bytes is blittable (same layout managed vs unmanaged), therefore
the framework will pin the array and pass a pointer. The pointer remains
valid during function call.


HTH,
greetings


TT (Tom Tempelaere) said:
Hi people,

I am wrapping a C dll using PInvoke from C#. I need to wrap the following signature in C:

int dma_start( const UCHAR* data, UINT data_length );

The function should start with a DMA operation, and I have to use it from
my C# program. I am really unsure what type of marshalling I should use.
The data parameter is a pointer to an array of byte data. This data must
not be copied when calling the function. Plus, the .NET framework should not
move the data around in memory until the method returns. Currently, I've
made the interop signature as follows:
[DllImport("UsedLib.dll", EntryPoint="dma_start")]
[return : MarshalAs(UnmanagedType.I4)]
public static extern bool DMAStart (
[MarshalAs(UnmanagedType.U1)] ref byte DMAData,
[MarshalAs(UnmanagedType.U4)] uint DMALength
);

Is this a good way to define the pointer to the array (DMAData)?
How do I say to the .NET framework that it shouldn't move the byte data
around in memory, until the method returns?
 
T

TT \(Tom Tempelaere\)

You can also declare it as :
public extern int dma_start ( byte[] data, uint data_length );

An array of bytes is blittable (same layout managed vs unmanaged), therefore
the framework will pin the array and pass a pointer. The pointer remains
valid during function call.

I wouldn't have to decorate the data parameter? What would be the right
decoration?

Thanks
 
B

BMermuys

Hi,

TT (Tom Tempelaere) said:
You can also declare it as :
public extern int dma_start ( byte[] data, uint data_length );

An array of bytes is blittable (same layout managed vs unmanaged), therefore
the framework will pin the array and pass a pointer. The pointer remains
valid during function call.

I wouldn't have to decorate the data parameter?

You don't have to decorate it.

HTH,
greetings
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top