0

I have a function definition in a native C++ file as follows:

void fun(byte* arg1, int* arg2, byte arg3) {}

So, from my C# file, I am calling the function as follows:

fun(ref byte[] arg1, ref int arg2, byte arg3);

Shouldn't pinvoke take care of this?

Tyler Durden
  • 1,188
  • 2
  • 19
  • 35
  • Forgetting to use DllImport.CallingConvention is a standard mistake. Your code snippet sucks. – Hans Passant Dec 19 '13 at 17:58
  • I used it, I just dint include it here. I was just focussing on the data types. Sorry, if my snippet doesnt match your high standards. I am still a learner – Tyler Durden Dec 19 '13 at 18:26

3 Answers3

2

I would suggest:

fun([MarshalAs(UnmanagedType.LPArray)] byte[] arg1, ref int arg2, byte arg3)

See MarshalAs and UnmanagedType.

The ref byte[] arg1 that you have corresponds to the C++ byte **.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
1

A byte[] is marshalled as a pointer to the first element of the array. Which is exactly what you need on the unmanaged side. You've used ref byte[] which has an extra, spurious, level of indirection. So your code can simply be:

[DllImport(...)]
fun(byte[] arg1, ref int arg2, byte arg3);

The marshaller handle the byte array by pinning it, and so the parameter will be in/out. Although I suspect that you will in fact only pass data from managed to unmanaged. But if your unmanaged code modified the array, then these modifications would actually be made directly to the pinned managed array.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

The first parameter is a pointer to a single byte object, which would translate to

public static extern void fun(ref byte arg1, ref int arg2, byte arg3);

If you meant to say that it's an array, I'd use an IntPtr

public static extern  void fun(ref IntPtr arg1, ref int arg2, byte arg3);

I find that the PInvoke Interop Assitant is pretty useful for this kind of stuff. Also see pinvoke.net for using a lot of standard DLL imports.

Matt
  • 2,682
  • 1
  • 17
  • 24
  • And how do you propose to pass a `byte[]` as an `IntPtr`? – Jim Mischel Dec 19 '13 at 19:04
  • Your answer is definitely slicker, I wasn't aware of that attribute. I would have done something similar to [this approach](http://stackoverflow.com/questions/537573/how-to-get-intptr-from-byte-in-c-sharp), though I would free the memory in a `finally` block. – Matt Dec 19 '13 at 19:49
  • It's not that it is slicker. It's more that your answer is wrong. You could use `IntPtr` rather than `ref IntPtr`, and manually marshal the array. For instance by pinning it. But that would not be a great idea. Fundamentally though, your code commits the same fault as the code in the question. You have one level of indirection too many. – David Heffernan Dec 19 '13 at 19:55