12

In an attempt to learn to use PInvoke in C#, I'm a little unsure how to handle various cases with pointers involving simple value types.

I'm importing the following two functions from an unmanaged DLL:

public int USB4_Initialize(short* device);
public int USB4_GetCount(short device, short encoder, unsigned long* value);

The first function uses the pointer as an input, the second as an output. Their usage is fairly simple in C++:

// Pointer as an input
short device = 0; // Always using device 0.
USB4_Initialize(&device);

// Pointer as an output
unsigned long count;
USB4_GetCount(0,0,&count); // count is output

My first attempt in C# results in the following P/Invokes:

[DllImport("USB4.dll")]
public static extern int USB4_Initialize(IntPtr deviceCount); //short*

[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, IntPtr value); //ulong*

How do I use these functions in C# in the same way as the C++ code above? Is there a better way to declare these types, perhaps using MarshalAs?

Will Eddins
  • 13,628
  • 5
  • 51
  • 85
  • 1
    Hey, USB 4 already? I'm still waiting for 3.0 – H H Sep 14 '09 at 17:05
  • 2
    I wish. It has nothing to do with USB4. This is just a USB device the company has for connecting to an encoder, and since it's the 4th revision of their product, they stupidly named the product USB4. – Will Eddins Sep 14 '09 at 17:09

2 Answers2

17

If the pointer is to a single primitive type and not an array, use ref / out to describe the parameter

[DllImport("USB4.dll")]
public static extern int USB4_Initialize(ref short deviceCount);

[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, ref uint32 value)

In these examples out is probably more appropriate but either will work.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
1

The .NET runtime can do a lot of that conversion (referred to as "marshaling") for you. While an explicit IntPtr will always do EXACTLY what you tell it to, you can likely substitute the ref keyword for a pointer like that.

[DllImport("USB4.dll")]
public static extern int USB4_Initialize(ref short deviceCount); //short*

[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, ref short value); //ulong*

You can then call them like this:

short count = 0;

USB4_Initialize(ref count);

// use the count variable now.
Adam Robinson
  • 182,639
  • 35
  • 285
  • 343