简体   繁体   中英

Passing a pointer to an array from C# to c DLL

I have a dll which has arguments with double*, eg xyz(double* a, double* b). I am using this DLL to pass two double arrays to function xyz. The problem is when I'm passing a double array by reference using a, the array is being updated but the values are rounded off which happens when you typecast something to and from int. Can you tell me an efficient way of sending this double array to c dll and getting the desired results in decimal. (Changing the DLL is not an option). Also I tried Marshal, I am not entirely sure if I did the right thing, but whenever I used to change the argument of xyz to xyz(IntPtr a, double* b) or something I used to get AccessViolationException, corrupt memory.

If I understand correctly, you are passing an array from C# to C (or C++) code. The problem with the approach of sending in the array directly to the method like xyz(double* a, double* b) is that the the code has no way of knowing the sizes of the arrays. This can get you access violation exceptions, once the C/C++ code tries to access an element that is out of the bounds of the array.

There are multiple ways around this - either using SafeArray from C# (that already contains the size attribute), sending the arrays to some bridging method with the sizes, or passing the data in a struct, like this:

internal struct ArraysStruct
{
    public int floatArraySize;
    public IntPtr floatArray;
    public int uintArraySize;
    public IntPtr uintArray; 
}

Which would then be matched on the C/C++ side by something like:

typedef struct ArraysStruct
{
    size_t floatArraySize;
    float* floatArray;
    size_t uintArraySize;
    unsigned int* uintArray;
}

You would need to use Marshal.AllocHGlobal() to allocate the arrays to the sizes first (in C#) and then Marshal.FreeHGlobal() once you're done with them.

Try following:

            double[] a = { 1.23, 2.34, 5.45 };
            IntPtr aptr = Marshal.AllocHGlobal(a.Length * sizeof(double));
            Marshal.Copy(a, 0, aptr, a.Length);
            double[] b = { 1.23, 2.34, 5.45 };
            IntPtr bptr = Marshal.AllocHGlobal(b.Length * sizeof(double));
            Marshal.Copy(b, 0, bptr, b.Length);

            xyz(aptr, bptr)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM