【问题标题】:Passing a pointer to an array from C# to c DLL将指向数组的指针从 C# 传递到 c DLL
【发布时间】:2020-08-19 18:39:17
【问题描述】:

我有一个带有double* 参数的dll,例如xyz(double* a, double* b)。我正在使用这个 DLL 将两个双精度数组传递给函数 xyz。问题是,当我使用 a 通过引用传递一个双精度数组时,该数组正在更新,但值被四舍五入,当您在 int 之间进行类型转换时会发生这种情况。你能告诉我一种将这个双数组发送到 c dll 并以十进制形式获得所需结果的有效方法吗? (更改 DLL 不是一种选择)。我也尝试了 Marshal,我不完全确定我是否做对了,但是每当我将 xyz 的参数更改为 xyz(IntPtr a, double* b) 或我曾经得到 AccessViolationException 的东西时,都会损坏内存。

【问题讨论】:

  • 将参数声明为double[] 并传递数组。很简单。您可能错误地使用了ref double[],但我们无法知道,因为您没有显示代码。
  • 从您的 cmets 关于“四舍五入”和“小数”的情况来看,我想知道您的互操作是否真的没有问题,也许您的问题在这里得到了真正解决:stackoverflow.com/questions/588004/…

标签: c# arrays pointers marshalling dllimport


【解决方案1】:

如果我理解正确,您将数组从 C# 传递到 C(或 C++)代码。将数组直接发送到xyz(double* a, double* b) 之类的方法的问题在于代码无法知道数组的大小。一旦 C/C++ 代码尝试访问超出数组边界的元素,这会使您访问冲突异常。

有多种方法可以解决这个问题 - 使用 C# 中的 SafeArray(已经包含 size 属性),将数组发送到具有大小的桥接方法,或者在结构中传递数据,如下所示:

internal struct ArraysStruct
{
    public int floatArraySize;
    public IntPtr floatArray;
    public int uintArraySize;
    public IntPtr uintArray; 
}

然后在 C/C++ 端匹配如下:

typedef struct ArraysStruct
{
    size_t floatArraySize;
    float* floatArray;
    size_t uintArraySize;
    unsigned int* uintArray;
}

您需要先使用 Marshal.AllocHGlobal() 将数组分配给大小(在 C# 中),然后在完成后使用 Marshal.FreeHGlobal()

【讨论】:

    【解决方案2】:

    尝试以下:

                double[] a = { 1.23, 2.34, 5.45 };
                IntPtr aptr = Marshal.AllocHGlobal(a.Length * sizeof(double));
                Marshal.Copy(a, 0, aptr, a.Length);
                double[] b = { 1.23, 2.34, 5.45 };
                IntPtr bptr = Marshal.AllocHGlobal(b.Length * sizeof(double));
                Marshal.Copy(b, 0, bptr, b.Length);
    
                xyz(aptr, bptr)
    

    【讨论】:

    • 不需要这样做。将参数声明为double[],然后简单地传递数组。编组器将固定数组并传递其第一个元素的地址。这比分配和复制更有效。
    猜你喜欢
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 2017-08-09
    • 2012-07-19
    • 1970-01-01
    相关资源
    最近更新 更多