2

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.

2
  • Declare the arguments as double[] and pass the array. Very simple. You perhaps wrongly used ref double[] but we can't know because you didn't show the code. Commented May 5, 2020 at 8:56
  • Judging from your comments about "rounded off" and "decimal" I wonder if there's actually nothing wrong with your interop, and perhaps your problem is really addressed here: stackoverflow.com/questions/588004/… Commented May 5, 2020 at 9:00

2 Answers 2

1

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)
Sign up to request clarification or add additional context in comments.

1 Comment

No need to do this. Declare the argument as double[] and then simply pass the array. The marshaller will pin the array and pass the address of its first element. That's more efficient than allocate and copy.
0

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.

Comments

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.