【问题标题】:Returning a variable sized array of doubles from C++ to C# - a simpler way?将可变大小的双精度数组从 C++ 返回到 C# - 一种更简单的方法?
【发布时间】:2010-10-01 08:36:13
【问题描述】:

我有以下 C++ 方法:

__declspec(dllexport) void __stdcall getDoubles(int *count, double **values); 该方法分配并填充一个 double 数组,并将 *count 设置为数组的大小。

我设法通过 pinvoke 让它工作的唯一方法是:

[System.Runtime.InteropServices.DllImportAttribute("xx.dll")]
 public static extern void getDoubles(ref int count, ref System.IntPtr values);

用法是:

int count = 0;
IntPtr doubles = new IntPtr();
Nappy.getDoubles(ref count, ref doubles);
double[] dvs = new double[count];
for(int i = 0;i < count;++{
    dvs[i] = (double)Marshal.PtrToStructure(doubles, typeof(System.Double));
    doubles = new IntPtr(doubles.ToInt64()+Marshal.SizeOf(typeof(System.Double)));
}

这些值最终出现在 dvs 数组中。 有没有更好的方法来做到这一点而不涉及托管语言中的指针运算......

【问题讨论】:

  • 描述不完整——它是如何分配内存的,又是如何返回给那个分配器的?

标签: c# c++ arrays pinvoke


【解决方案1】:

我认为你可以使用

Marshal.Copy( source, destination, 0, size );

【讨论】:

    【解决方案2】:

    您需要更改非托管方法签名,使其如下所示:

    __declspec(dllexport) void __stdcall getDoubles(SAFEARRAY *array); 
    

    那么您应该可以使用以下托管版本的功能:

    [System.Runtime.InteropServices.DllImportAttribute("xx.dll")]
    public static extern void getDoubles(
                  [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_R8)]
                  double[] array
    );
    

    当然,您还必须重写非托管代码才能使用 SAFEARRAY。 更多关于这个话题can be found at MSDN.

    虽然有一个问题,我记得在 C# 中使用 ZLib 可以在没有任何包装器的情况下使用 byte[] 而非托管对应物是 BYTE*,您是否尝试过直接使用 double* / double[] ?

    【讨论】:

    • 我尝试过直接使用 double [] 或 ref double ,但这仅适用于单级间接。如果您知道托管端的大小,则支持编组一个双精度数组。
    猜你喜欢
    • 1970-01-01
    • 2015-05-27
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多