只为IntPtr创建一种任何类型的数组方法

cMi*_*nor 7 c#

有一个转换double[] dIntPtrlike 的方法:

public static IntPtr DoubleArrayToIntPtr(double[] d)
{
   IntPtr p = Marshal.AllocCoTaskMem(sizeof(double) * d.Length);
   Marshal.Copy(d, 0, p, d.Length);
   return p;
}
Run Code Online (Sandbox Code Playgroud)

什么是做的最好的方式int[],float[]我想在做每类一个方法,如添加INT []等:

public static IntPtr IntArrayToIntPtr(int[] d)
{
   IntPtr p = Marshal.AllocCoTaskMem(sizeof(int) * d.Length);
   Marshal.Copy(d, 0, p, d.Length);
   return p;
}
Run Code Online (Sandbox Code Playgroud)

1.可以将这个方法被推广,如果是的话怎么样?

2.是否有可能只在一行代码中获取指针(As Marshal是无效方法)?

Eri*_*rik 4

最好的方法是为每种类型创建一个扩展类来为您执行此操作。您不能将其设为通用,因为Marshal.Copy()不支持通用类型。因此,您必须为每种类型重复您的方法bytecharintlongfloatdouble等。但是,您可以创建一个通用辅助方法来确定您的大小Marshsal

下面的内容可能对您有用:

public static class MarshalExtender
{
    public static IntPtr CopyToCoTaskMem(this byte[] array)
    {
        var ptr = AllocArrayCoTaskMem(array);

        Marshal.Copy(array, 0, ptr, array.Length);
        return ptr;
    }

    // Copy the above method and replace types as needed (int, double, etc).

    // Helper method for allocating bytes with generic arrays.
    static IntPtr AllocArrayCoTaskMem<T>(T[] array)
    {
        var type = typeof(T);
        var size = Marshal.SizeOf(type) * array.Length;
        return Marshal.AllocCoTaskMem(size);
    }
}
Run Code Online (Sandbox Code Playgroud)

主要好处是在您的代码中您可以轻松执行以下操作:

var myArray = { 0, 1, 2, 3, 4, 5, ... }
var ptr = myArray.CopyToCoTaskMem();
Run Code Online (Sandbox Code Playgroud)

注意:Marshal.FreeCoTaskMem()完成后一定要打电话!我建议您的扩展方法返回一个IDisposable对象,以便您可以将其包装在一个using块中。

例如:

public sealed class CoTaskMemoryHandle : IDisposable
{
    bool isDisposed;
    readonly IntPtr handle;

    public IntPtr Handle { get { return handle; } }

    public CoTaskMemoryHandle(IntPtr handle)
    {
        this.handle = handle;
    }

    public void Dispose()
    {
        OnDispose(true);
        GC.SuppressFinalize(this);
    }

    void OnDispose(bool isDisposing)
    {
        if (isDisposed) return;

        if (isDisposing)
        {
            if (handle != IntPtr.Zero)
                Marshal.FreeCoTaskMem(handle);
        }

        isDisposed = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你修改后的扩展类方法:

public static CoTaskMemoryHandle CopyToCoTaskMem(this byte[] array)
{
    var ptr = AllocArrayCoTaskMem(array);

    Marshal.Copy(array, 0, ptr, array.Length);
    return new CoTaskMemoryHandle(ptr);
}
Run Code Online (Sandbox Code Playgroud)

这样你就可以安全地封装Alloc/Free平衡:

using(myArray.CopyToCoTaskMem())
{
   // Do something here..
}
Run Code Online (Sandbox Code Playgroud)