6

(I understand this might be duplicate but I don't understand the other threads)

I'm working with C# an I have a third party dll that needs int arrays (or pointers to int array) as parameters. How do I marshal an int array between C# and C/C++ ? The functions are declared like this:

// reads/writes int values from/into the array
__declspec(dllimport) void __stdcall ReadStuff(int id, int* buffer);

In C int* would be a pointer right ? So I'm confused if I have to use IntPtr or if I could use int[] (preferred) ? I thought this might be ok:

[DllImport(dllName)]
static extern void ReadStuff(int id, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)] ref int[] buffer);

// call
int[] array = new int[12];
ReadStuff(1, ref array);

Would that work ? Or how do I have to declare this function in C# in safe code ?

2 Answers 2

5

It isn't a SafeArray. A SafeArray is something connected to Variants and the good old times of OLE :-) It probably lives in the dictionary near the word "dodo".

It is:

[DllImport(dllName, CallingConvention=CallingConvention.StdCall)]
static extern void ReadStuff(int id, int[] buffer);

the marshaler will do the "right" thing.

or

[DllImport(dllName, CallingConvention=CallingConvention.StdCall)]
static extern void ReadStuff(int id, IntPtr buffer);

but then it's more complex to use.

The CallingConvention=CallingConvention.StdCall is the default one, so it isn't necessary to write it out explicitly.

You use this way:

// call
int[] array = new int[12];
ReadStuff(1, array);

A ref int[] would be a int** (but it could be complex to pass, because normally you RECEIVE the array, not SEND the array :-) )

Note that your "interface" is quite poor: you can't tell to ReadStuff the length of your buffer, nor can you receive the necessary length of the buffer, nor can you receive the number of characters of the buffer that were really used.

0
1

You could do something like this:

[DllImport(dllName)]
static extern void ReadStuff(int id, IntPtr buffer, int length);


int[] array = new int[12];

unsafe
{
  fixed (int* data = &array[0])
    ReadStuff(1, (IntPtr)data, array.Length);
}

C++ code: (not tested)

extern "C" __declspec(dllexport) VOID WINAPI ReadStuff(int id, int* buffer, int length);  
3
  • As a sidenote, int* data = &array[0] can be shortened as int* data = array (like in C/C++)
    – xanatos
    Commented Aug 7, 2013 at 12:58
  • I would rather avoid using unsafe code. I've never used it and I don't see why I should start. Also like I said it's a third party DLL. I can't change the signatures of functions.
    – Bitterblue
    Commented Aug 7, 2013 at 15:34
  • I think, if you want to communicate a buffer/pointer to unmanaged, you'll need unsafe/fixed Commented Aug 8, 2013 at 8:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.