Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#从C+编组双*+;动态链接库? 我有一个C++函数,它有一个导出函数: extern "C" __declspec(dllexport) double* fft(double* dataReal, double* dataImag) { [...] }_C#_C++_Interop_Marshalling_Dllimport - Fatal编程技术网

C#从C+编组双*+;动态链接库? 我有一个C++函数,它有一个导出函数: extern "C" __declspec(dllexport) double* fft(double* dataReal, double* dataImag) { [...] }

C#从C+编组双*+;动态链接库? 我有一个C++函数,它有一个导出函数: extern "C" __declspec(dllexport) double* fft(double* dataReal, double* dataImag) { [...] },c#,c++,interop,marshalling,dllimport,C#,C++,Interop,Marshalling,Dllimport,该函数计算两个双数组(实数组和虚数组)的FFT,返回一个双数组,其中实数组和虚数组的分量交错:{Re,Im,Re,Im,…} 我不知道如何在C#中调用此函数。 我正在做的是: [DllImport("fft.dll")] static extern double[] fft(double[] dataReal, double[] dataImag); 当我这样测试它时: double[] foo = fft(new double[] { 1, 2, 3, 4 }, new double[] {

该函数计算两个双数组(实数组和虚数组)的FFT,返回一个双数组,其中实数组和虚数组的分量交错:{Re,Im,Re,Im,…}

我不知道如何在C#中调用此函数。 我正在做的是:

[DllImport("fft.dll")]
static extern double[] fft(double[] dataReal, double[] dataImag);
当我这样测试它时:

double[] foo = fft(new double[] { 1, 2, 3, 4 }, new double[] { 0, 0, 0, 0 });
double[] foo = new double[8];
fft(new double[] { 1, 2, 3, 4 }, new double[] { 0, 0, 0, 0 }, 4, out foo);
我得到一个MarshalDirectiveException异常:

无法封送“返回值”:无效的托管/非托管类型组合

我假设这是因为C++<代码>双*与C++代码> double []/CODE >不太一样,但我不知道如何修复它。有什么想法吗

编辑: 我已更改签名,以便现在传递一些额外信息:

extern "C" __declspec(dllexport) void fft(double* dataReal, double* dataImag, int length, double* output);
我们总是知道
输出的长度
将是2倍
长度

测试如下:

double[] foo = fft(new double[] { 1, 2, 3, 4 }, new double[] { 0, 0, 0, 0 });
double[] foo = new double[8];
fft(new double[] { 1, 2, 3, 4 }, new double[] { 0, 0, 0, 0 }, 4, out foo);

现在我得到的是AccessViolationException,而不是MarshalDirectiveException。

您的示例存在一些问题:

C++代码不知道这些数组有多大。封送拆收器将向它们传递一个有效指针,但如果没有相应的长度参数,则无法判断它们有多大。在大多数平台上,sizeof(dataReal)和sizeof(dataImag)可能是4或8(即sizeof(void*))。可能不是你想要的
  • 虽然可以将指针封送回作为返回值(然后可以使用它来填充托管数组),但返回值的内存没有隐含的所有者,因此存在内存泄漏的可能性。缓冲区是否在fft内部分配了新的缓冲区?如果是这样,那么您需要另一个导出,托管代码可以调用该导出来释放内存或使用LocalAlloc(然后在托管端使用Marshal.FreeHGlobal)。这充其量是有问题的
  • 相反,我的建议是这样定义fft:

    
    extern "C" __declspec(dllexport) void __stdcall fft(double const* dataReal, int dataRealLength, double const* dataImag, int dataImagLength, double* result, int resultLength)
    {
      // Check that dataRealLength == dataImagLength
      // Check that resultLength is twice dataRealLength
    }
    
    相应的p/Invoke签名为:

    
    [DllImport("fft.dll")]
    static extern void fft(double[] dataReal, int dataRealLength, double[] dataImag, int dataImagLength, double[] result, int resultLength);
    
    然后是一个调用的示例:

    
    double[] dataReal = new double[] { 1.0, 2.0, 3.0, 4.0 };
    double[] dataImag = new double[] { 5.0, 6.0, 7.0, 8.0 };
    double[] result = new double[8];
    fft(dataReal, dataReal.Length, dataImag, dataImag.Length, result, result.Length);
    

    编辑:根据描述的fft操作进行更新。

    无需更改签名。 您可以使用以下命令:

    [DllImport( "fft.dll", EntryPoint = "fft" )]
    public static extern IntPtr fft( double[] dataReal, double[] dataImag );
    
    然后需要从返回的
    IntPtr
    复制字节。因为您知道输出的大小是输入的两倍,所以可以按以下方式执行:

    double[] result = new double[ doubleSize ];
    Marshal.Copy( pointer, result, 0, doubleSize );
    
    结果将包含
    fft
    函数返回的字节

    编辑:
    我相信您会发现
    P/Invoke Interop Assistant
    工具很有用:

    这不是很好的Interop原型。有两种方法可以解决此问题:

  • 更改C++函数原型并通过参数返回所有双倍(希望你有C++ FUNC的源码)
  • 使用休止翼所述的IntPtr
  • 只有在使用CoTaskMemAlloc函数分配内存的情况下,返回内存引用才能正常工作。否则,在释放内存期间,您将出现运行时异常(CLR始终尝试使用CoTaskMemFree释放返回内存)


    <>我认为最好的方法是第一种方式,它在Peter Huene的回答中描述。

    它不能将C++ <代码>双*<代码>转换成C<代码> double []/COD>。因为封送代码不知道数组有多长。根据你的描述,我假设它是输入数组的两倍,但是我不知道C++函数是如何知道输入数组的长度的。C++函数决定数组长度:int lengthImag=sizeof(dataImag)/sizeof(double);不,没有
    dataReal
    只是一个指向
    double
    的指针,它的大小与数组中的元素数无关,这就是数组在C(++)中作为参数传递的方式。另外:我们不知道谁的工作是释放结果数组(以及如何释放)。好的,我明白了。(对不起,我在C#vs C/C++方面的经验要丰富得多)。那么我还需要传递数组的长度吗?至于释放,它们不是在堆栈中吗?这意味着当函数结束时,内存会自动释放?如果不是,你建议我如何释放它?只是想澄清一下:你实际上是指double[]result=double[8],对吗?是的。我没有密切注意fft的实际功能。根据您的要求,您可以通过值传递resultLength。