IntPtr 大小的问题

Posted

技术标签:

【中文标题】IntPtr 大小的问题【英文标题】:issue with size of IntPtr 【发布时间】:2013-11-27 12:10:43 【问题描述】:

昨天,我发布了一个关于将一些 int** 和 double** 从 C# 传递到 C++ 的问题。 How to import a C++ function with int** and double** parameters

幸运的是,我得到了一些很好的帮助。这是我的新代码:

[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;
    

当我的两个数组 Pointer 和 Time 的长度为 2 时,我没有问题。但是当我将它增加到 4 时,我的代码就会崩溃。我调试了一下,似乎当它试图访问 Pointer 的第 4 个元素时,这个元素指向 x00000,因此无法访问。 我尝试了不同的事情但没有成功。 有关如何解决此问题的任何想法?

【问题讨论】:

这段代码有非常严重的错误,永远不能像写的那样工作。非托管函数的语义非常重要,但非常不清楚。很确定你完全错误地使用它,它需要稳定的内存指针,指向数组的指针数组,并且 not 在调用后将它们取消分配。 fixed 的使用是非常错误的。我强烈建议您在 C++/CLI 中编写一个包装器,而不是尝试调用它。 是的,Hans 所说的,一个不平凡的 pinvoke 是两场战斗,让代码编译只是第一场,让它真正正确运行完全是另一个蠕虫球,可以蜡,随便什么,。 【参考方案1】:

如果有人遇到同样的问题,我已经找到了解决方案:

C++ 代码:

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

C#代码:

[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;
    

【讨论】:

以上是关于IntPtr 大小的问题的主要内容,如果未能解决你的问题,请参考以下文章

知道内存中一个图片的指针IntPtr大小,转换成图片显示

C# IntPtr类型和使用/unsafe选项编译程序

给定 IntPtr 句柄,更改 Window 背景颜色

内存中一个图片的指针IntPtr

System::IntPtr 到 C++/CLI 中的 int*

对于intptr_t和uintptr_t的理解