Question

Yesterday, I posted an issue regarding passing some int** and double** from C# to C++. How to import a C++ function with int** and double** parameters

Fortunately, I got some good help. Here is my new code:

[DllImport("opendsp.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern int SetAcquisitionPointerSynchronously(int* ID, int* BufferID, out IntPtr Pointer, out IntPtr Time, int NumberOfPointers);

public unsafe int OpenDSP_SetAcquisitionPointerSynchronously(int[] IDs, int[] BufferID, ref int[] Pointer, ref double[] Time, int NumberOfPointers)
{
    IntPtr fQueue = IntPtr.Zero;
    IntPtr fTime = IntPtr.Zero;
    int breturn = -1;
    fixed (int* fMeasurementId = IDs)
    fixed (int* fBufferID = BufferID)

    try
    {
        fQueue = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)) * Pointer.Length);

        fTime = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Double)) * Time.Length);

        breturn = SetAcquisitionPointerSynchronously(fMeasurementId, fBufferID, out fQueue, out fTime, NumberOfPointers);

        int size = Marshal.SizeOf(typeof(double));
        for (uint i = 0; i < NumberOfPointers; i++)
            Time[i] = (double)Marshal.PtrToStructure(new IntPtr(fTime.ToInt32() + (size * i)), typeof(double));

        size = Marshal.SizeOf(typeof(int));
        for (uint i = 0; i < NumberOfPointers; i++)
            Pointer[i] = (int)Marshal.PtrToStructure(new IntPtr(fQueue.ToInt32() + (size * i)), typeof(int));

        Marshal.FreeHGlobal(fQueue);
        Marshal.FreeHGlobal(fTime);
    }
    catch {
    }

    return breturn;
}

When my two arrays Pointer and Time are of length 2, I don't have issues. But when I increase it to 4, then my code crashes. I debugged, and it seems that when it tries to access the 4th elements of Pointer, this one points to 0x00000 so it is not accessible.

I have tried different things without success.

How can I fix this?

Was it helpful?

Solution

In case, someone gets the same problem, I have found a solution:

C++ code:

int SetPointers(int* ID, int* BufferID, int** Pointer, double** Time, int NumberOfPointers);

C# code:

[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern Int32 SetPointers(Int32[] ID, Int32[] BufferID, IntPtr[] Pointer, IntPtr[] Time, int NumberOfPointers);
    public unsafe int SetPointers(int[] IDs, int[] BufferID, ref int[] Pointer, ref double[] Time, int NumberOfPointers)
    {
        int breturn = -1;

        IntPtr[] queue = new IntPtr[NumberOfPointers];
        IntPtr[] time = new IntPtr[NumberOfPointers];
        for (int i = 0; i < NumberOfPointers; i++)
        {
            queue[i] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)));
            time[i] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)));
        }
        breturn = SetPointers(IDs, BufferID, queue, time, NumberOfPointers);

        if (breturn >= 0)
        {
            for (int i = 0; i < NumberOfPointers; i++)
            {
                Pointer[i] = (int)Marshal.ReadInt32(queue[i]);
                Time[i] = (double)Marshal.PtrToStructure(new IntPtr(time[i].ToInt32()), typeof(double));
            }
        }
        return breturn;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top