P / Invoke包含C#和C之间的双编组数据数组

前端之家收集整理的这篇文章主要介绍了P / Invoke包含C#和C之间的双编组数据数组前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经阅读了使用P / Invoke herehere的C Interop上的各种MSDN页面,但我仍然感到困惑.

我有一些大型的双打数组,我需要进入本机代码,以及一些需要返回的结果数组.我事先并不知道输出数组的大小.为简单起见,我将在示例中仅使用单个数组.该平台是x64;我读到在32位和64位环境之间编组内部是完全不同的,所以这可能很重要.

C#

[DllImport("NativeLib.dll")]
    public static extern void ComputeSomething(double[] inputs,int inlen,[Out] out IntPtr outputs,[Out] out int outlen);

    [DllImport("NativeLib.dll")]
    public static extern void FreeArray(IntPtr outputs);

    public void Compute(double[] inputs,out double[] outputs)
    {           
        IntPtr output_ptr;
        int outlen;
        ComputeSomething(inputs,inputs.Length,out output_ptr,out outlen);

        outputs = new double[outlen];
        Marshal.Copy(output_ptr,outputs,outlen);

        FreeArray(output_ptr);
    }

C

extern "C" 
{
    void ComputeSomething(double* inputs,int input_length,double** outputs,int* output_length)
    {
    //...
    *output_length = ...;
    *outputs = new double[output_length];
    //...
    }

    void FreeArray(double* outputs)
    {
        delete[] outputs;
    }
}

它有效,也就是说,我可以读出我在C侧写入数组的双打.不过,我想知道:

>这真的是使用P / Invoke的正确方法吗?
>我的签名不是很复杂吗?
>可以更有效地使用P / Invoke来解决这个问题吗?
>我相信我读过可以避免对内置类型的单维数组进行编组. Marshal.Copy有办法吗?

请注意,我们有一个可用的C/C++li版本,但是在第三方库代码中存在与导致崩溃的本地静态相关的一些问题. Microsoft marked this issue as WONTFIX,这就是为什么我在寻找替代品.

解决方法

如果将确定输出长度的代码与填充输出代码分开是可行的,那么您可以:

>导出返回输出长度的函数.
>从C#代码调用它,然后分配输出缓冲区.
>再次调用非托管代码,这次要求它填充输出缓冲区.

但我假设你拒绝了这个选项,因为它是不切实际的.在这种情况下,您的代码解决问题的完美合理方式.事实上,我会说你做得很好.

修复调用约定不匹配后,代码在x86中的工作方式相同.在C方面,调用约定是cdecl,但在C#方面它是stdcall.这与x64无关,因为只有一个调用约定.但是在x86下这将是一个问题.

一些评论

>您不需要使用[Out]和out.后者意味着前者.>您可以通过分配共享堆来避免导出deallocator.例如,C端的CoTaskMemAlloc,然后在C#端释放Mashal.FreeCoTaskMem.

原文链接:https://www.f2er.com/csharp/243995.html

猜你在找的C#相关文章