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