簡體   English   中英

具有P / Invoke和指針的泛型

[英]Generics with P/Invoke and pointers

我正在使用具有回調函數的C接口,其中軟件正在處理指針。

在C#方面,我有以下代碼用於將指針復制到托管數組並返回,例如用於float *

class FloatPointer
{
    readonly unsafe float* _pointer;

    public uint Size { get; set; }

    public float[] Array { get; set; }

    public unsafe void CopyToPointer ()
    {
        int length = (int)Math.Min (Size, Array.Length);
        Marshal.Copy (Array, 0, (IntPtr)_pointer, length);
        for (int i = length; i < Size; i++) {
            _pointer [i] = 0;
        }
    }

    unsafe float[] CopyFromPointer ()
    {
        float[] result = new float[Size];
        Marshal.Copy ((IntPtr)_pointer, result, 0, (int)Size);
        return result;
    }

    public unsafe FloatPointer (float* pointer, uint size)
    {
        _pointer = pointer;
        Size = size;
        Array = CopyFromPointer ();
    }
}

因為我必須對unsigned char*uint*等做同樣的事情,所以我在考慮使用泛型類, class Pointer<T>: where T: ValueType

不幸的是,這種限制是不可能的。

如果我將其更改為無限制的泛型類,那么Marshal.Copy告訴我它不知道T[]

有沒有辦法創建這個泛型類?

我相信這門課會做你想做的。 它具有從數組轉換為指針和返回的方法,以及作為泛型類型參數。

public class StructPointer<T> where T : struct
{
    /// <summary>
    /// Pointer
    /// </summary>
    public IntPtr Pointer { get; set; }

    /// <summary>
    /// Number of elements in pointer
    /// </summary>
    public int PointerElementCount { get; set; }

    /// <summary>
    /// Array
    /// </summary>
    public T[] Array { get; set; }

    private int sizeOfT;

    /// <summary>
    /// Copy Array to Pointer
    /// </summary>
    public void ArrayToPointer()
    {
        if (Array == null || Pointer == IntPtr.Zero)
        {
            return;
        }

        int length = (int)Math.Min(PointerElementCount, Array.Length);
        int byteCount = length * sizeOfT;
        GCHandle handle = GCHandle.Alloc(Array, GCHandleType.Pinned);
        unsafe
        {
            for (int i = 0; i < byteCount; i++)
            {
                *(((byte*)Pointer) + i) = *(((byte*)handle.AddrOfPinnedObject()) + i);
            }
        }
        handle.Free();

        if (PointerElementCount > Array.Length)
        {
            unsafe
            {
                int byteCount2 = byteCount + (sizeOfT * (PointerElementCount - Array.Length));
                for (int i = byteCount; i < byteCount2; i++)
                {
                    *(((byte*)Pointer) + i) = 0;
                }
            }
        }
    }

    /// <summary>
    /// Copy Pointer to Array
    /// </summary>
    public void ArrayFromPointer()
    {
        if (Pointer == IntPtr.Zero)
        {
            return;
        }

        Array = new T[PointerElementCount];
        GCHandle handle = GCHandle.Alloc(Array, GCHandleType.Pinned);
        int byteCount = Array.Length * sizeOfT;
        unsafe
        {
            for (int i = 0; i < byteCount; i++)
            {
                *(((byte*)handle.AddrOfPinnedObject()) + i) = *(((byte*)Pointer) + i);
            }
        }
        handle.Free();
    }

    public StructPointer()
    {
        sizeOfT = Marshal.SizeOf(typeof(T));
    }

    /// <summary>
    /// Constructor. Copies pointer to Array.
    /// </summary>
    /// <param name="pointer">Pointer</param>
    /// <param name="length">Number of elements in pointer</param>
    public StructPointer(IntPtr pointer, int length)
    {
        sizeOfT = Marshal.SizeOf(typeof(T));
        Pointer = pointer;
        PointerElementCount = length; // number of elements in pointer, not number of bytes
        ArrayFromPointer();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM