【问题标题】:Marshal.Copy Throws ArgumentOutOfRangeExceptionMarshal.Copy 引发 ArgumentOutOfRangeException
【发布时间】:2019-11-30 11:08:29
【问题描述】:

我正在尝试将 C# 应用程序中托管内存中的数据编组到非托管内存位置以供专有 DLL 使用。该值是一个浮点数,但 DLL 需要一个指向浮点数的指针。在构造函数中,我的想法是给指针分配非托管内存,然后将传入的浮点值复制到非托管内存中。

internal class MyInternalClass
{
    private static float[] fltArry;

    public struct MY_DLL_STRUCT
    {
        public IntPtr fltPtr;

        public MY_DLL_STRUCT(float flt)
        {
            MyInternalClass.fltArry = new float[] { flt };
            this.fltPtr = Marshal.AllocHGlobal(sizeof(float) * MyInternalClass.fltArry.Length);
            Marshal.Copy(MyInternalClass.fltArry, 0, this.fltPtr, sizeof(float) * MyInternalClass.fltArry.Length);
        }
    }
}

尺寸对我来说看起来不错,但是每当调用 Marshal.Copy 函数时,就会抛出 ArgumentOutOfRangeException。有什么想法吗?

【问题讨论】:

  • 您的非托管函数实际上是否采用浮点数组,或者只是一个指向它用来修改/输出单个值的单个浮点的指针?如果是后者,您可以通过将参数声明为ref floatout float(取决于它是否读取输入)来简化生活。可以使用[MarshalAs(Unmanagedtype.ByValArray, SizeConst = 1)] 声明结构中一个元素的单个静态大小的数组,而无需显式分配非托管内存。只有当你真的拥有不止一个价值时,事情才会变得更加复杂。
  • @JeroenMostert 这看起来很有趣。是的,它只是一个指向单个浮点值的指针。您介意发布一个答案并举例说明它应该如何使用吗?我不确定您建议的 MarshalAs 语句应该放在哪里。
  • 在没有看到非托管函数/结构声明的情况下,很难判断适当的互操作代码是什么。您在此处显示的代码对任何非托管资源都没有任何作用,它只是将单个 float 放入非托管内存块中。你如何处理生成的fltPtr
  • @JeroenMostert 哈哈,我希望我知道!我得到的只是头文件和编译后的 DLL。
  • 只需要 (C) 标头即可;这就是我所说的“非托管声明”。大概有一个它接受的结构指针和/或您调用的函数。该函数的签名/struct 的声明在这里是合适的。如果你只知道你必须咳出一个 IntPtr 并且它必须是某个类中的一个字段,那么这仍然是矫枉过正(你打算如何释放内存?)但并非完全不合理。

标签: c# marshalling dllimport outofrangeexception


【解决方案1】:

Marshal.Copy 的最后一个参数是number of elements to copy

我怀疑你应该使用1(或MyInternalClass.fltArry.Length)而不是sizeof(float) * MyInternalClass.fltArry.Length。您传递的值太大,因此:

例外情况

ArgumentOutOfRangeException - startIndex 和 length 不是 有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 1970-01-01
    • 2014-12-21
    • 1970-01-01
    • 2013-02-12
    相关资源
    最近更新 更多