LamdaComplex
LamdaComplex

Reputation: 891

Passing delegate to a unmanaged method which expects a delegate method with an int array pointer

I am working on a C# application which uses an unmanaged dll which as a method that takes in a function pointer as one of it's parameters. As I do not have access to the actual C++ source code for the unmanaged dll I can only rely on a snippet I have from a C++ sample which uses that the same dll. The problem I am having is that the delegate I have made to pass into the unmanaged method is not working.

Below is the DllImport of the method I am trying to use which takes the delegate I've created:

[DllImport("pos_tk.dll")]
static internal extern ErrorCode AddSIGHandle([MarshalAs(UnmanagedType.FunctionPtr)] SIG_Callback func);

Here is the delegate signature I currently have:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void SIG_Callback ([MarshalAs(UnmanagedType.LPArray)] ref int[] buf, int rev, object sender);

And this is the function the C++ sample snippet uses in which I based my delegate off of:

void __stdcall point_handle (int *buf, int rev, LPVOID pParam)

Now, before you tell me to change the ref int[] buf parameter of my delegate to ref int buf the program will throw an InvalidVariant error once the callback is attempted. The code snippet uses int *buf as an array of size rev.

Using the code I have above, the application throws an AccessViolationException when the callback is attempted. My hunch is that I should be using a different type for the ref int[] buf parameter, but I've tried everything I can think of. I've also been searching Google, SO, and MSDN all day but with no luck.

Anyone have any ideas?

As a final note, is this any way similar to how you can use a StringBuilder as a parameter for a unmanaged method that takes a char* parameter to retrieve a variable length string?

Upvotes: 4

Views: 2505

Answers (1)

JerKimball
JerKimball

Reputation: 16904

Passing arrays back and forth is always a PITA...try this signature, it seems applicable:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void point_handle(
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
    int[] buf,
    int rev,
    IntPtr pParam);

EDIT: just to elaborate, when you've got a "C style" array (that is a T*) as well as the length both specified in the arguments, SizeParamIndex is your salvation; basically it says "Hey, there's an unknown-length array coming in, but the parameter at this index will tell you how many of them there are. Use both that and the type to help marshal"

Upvotes: 4

Related Questions