2

I am completely confused with how to go about calling functions in native dll with array arguments.

Example:

The function is defined in the C# project as:

[DllImport("Project2.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
static extern void modifyArray([MarshalAs(UnmanagedType.LPArray)] int[] x, int len);

And the function call is:

modifyArray(arr, 3)

where arr = {4,5,6}

The native C++ function definition is as follows:

extern "C" _declspec(dllexport) void modifyArray(int* x,int len)
{   
        int arr[] = {1,2,3};
        x = arr;
}

Why in the C# project, the array is not pointing to the new array after the function call? It still remains {4,5,6}.

I tried this to but failed

[DllImport("Project2.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
static extern void modifyArray([In,Out] int[] x, int len);

This pinvoke fails whenever I try modifying arguments passed to these functions using pointers. Otherwise, I have had success passing ref array arguments for native dll sort functions where there is no pointer changes to newly created types.

1
  • Your C++ code is invalid, don't try to pinvoke code until you've got it working in C++ first. Commented Jan 3, 2014 at 18:06

2 Answers 2

3

Your C++ code is broken. The caller allocates the array, and the callee populates it. Like this:

extern "C" _declspec(dllexport) void modifyArray(int* x, int len)
{   
    for (int i=0; i<len; i++)
        x[i] = i;
}

As far as your p/invoke call goes, SetLastError should not be true. The function is not calling SetLastError. It should be:

[DllImport("Project2.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void modifyArray(int[] x, int len);
Sign up to request clarification or add additional context in comments.

Comments

1

This has nothing to do with PInvoke, this is just a plain old C issue. You would have the exact same problem if you called modifyArray from C

int* pArray = NULL;
modifyArray(pArray, len);
pArray == NULL;  // true! 

In modifyArray you are trying to change where x points to. This change won't be visible to the calling function because the pointer is passed by value. In order to change where it points to you need to pass a double pointer

void modifyArray(int** x, int len) { 
  *x = ...;
}

Note that you are currently trying to return stack allocated memory instead of heap allocated memory. That is incorrect and will lead to problems down the line

7 Comments

This gets him into a lot more trouble, best to recommend him to copy the elements instead.
I wrote this as a sample code, but the c++ code is much more complex and I can't modify it. So, I think what JaredPar answered will be best in my case. But, when I tried this, with changing the argument type to ref int[], it failed
That is, how should modifyArray be defined in the C# file
I did modify the C++ code, but only the first element of the array gets modified, I think to the address of the array in the C++ function.
In addition, even when using a "double pointer", never pass a pointer to something allocated on the stack out of the function - it will be undefined where it points to later...
|

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.