C#从C++DLL编组双*?我有一个带有导出函数的C++DLL:extern"C"__declspec(dllexport)double*fft(double*dataReal,double*dataImag){[...]}这个函数计算两个双精度数组(实数和虚数的FFT),返回一个双精度数组,实数与虚数分量交错:{Re,Im,Re,Im,...}我不知道如何在C#中调用此函数。我正在做的是:[DllImport("fft.dll")]staticexterndouble[]fft(double[]dataReal,double[]dataImag);当我这样测试时:double[]foo=fft(newdouble[]{1,2,3,4},newdouble[]{0,0,0,0});我得到MarshalDirectiveExceptionexception:无法编组“返回值”:无效的托管/非托管类型组合。我假设这是因为C++double*与C#double[]不完全相同,但我不确定如何修复它。有任何想法吗?编辑:我更改了签名,以便我现在传递一些额外信息:extern"C"__declspec(dllexport)voidfft(double*dataReal,double*dataImag,intlength,double*output);我们总是知道输出长度是长度的两倍[DllImport("fft.dll")]staticexternvoidfft(double[]dataReal,double[]dataImag,intlength,outdouble[]output);测试如下:double[]foo=newdouble[8];fft(newdouble[]{1,2,3,4},newdouble[]{0,0,0,0},4,outfoo);现在我得到一个AccessViolationException而不是MarshalDirectiveException。您的示例存在一些问题:C++代码不知道这些数组有多大。编组器将向它们传递一个有效的指针,但没有相应的长度参数,就无法判断它们有多大。sizeof(dataReal)和sizeof(dataImag)在大多数平台上可能是4或8(即sizeof(void*))。可能不是你想要的。虽然可以将指针编组为返回值(然后可用于填充托管数组),但不存在返回值内存的隐含所有者,从而增加了内存泄漏的可能性。fft中是否分配了新的缓冲区?如果是这样,那么您需要另一个导出,托管代码可以调用它来释放内存或使用LocalAlloc(然后在托管端使用Marshal.FreeHGlobal)。这充其量是有问题的。相反,我的建议是这样定义fft:extern"C"__declspec(dllexport)void__stdcallfft(doubleconst*dataReal,intdataRealLength,doubleconst*dataImag,intdataImagLength,double*result,intresultLength){//检查thatdataRealLength==dataImagLength//检查resultLength是dataRealLength的两倍}相应的P/Invoke签名将是:[DllImport("fft.dll")]staticexternvoidfft(double[]dataReal,intdataRealLength,double[]dataImag,intdataImagLength,double[]结果,intresultLength);然后是调用示例:double[]dataReal=newdouble[]{1.0,2.0,3.0,4.0};double[]dataImag=newdouble[]{5.0,6.0,7.0,8.0};双[]结果=新双[8];fft(dataReal,dataReal.Length,dataImag,dataImag.Length,结果,result.Length);编辑:如所述用fft更新。无需更改签名。你可以使用这样的东西:[DllImport("fft.dll",EntryPoint="fft")]publicstaticexternIntPtrfft(double[]dataReal,double[]dataImag);然后你需要从返回的IntPtrFestival中复制单词。由于您知道输出将是输入大小的两倍,因此您可以这样做:double[]result=newdouble[doubleSize];Marshal.Copy(指针,结果,0,doubleSize);result将包含fft函数返回的字节。编辑:我相信您会发现P/InvokeInteropAssistant工具很有用:Managed,Native,andCOMInterop这不是互操作的好原型。您可以通过两种方式解决此问题:更改C++函数原型并通过参数返回所有双精度数(我希望您有C++函数的源代码)只有在使用CoTaskMemAlloc函数分配内存时才使用RestWing描述的IntPtr在此在这种情况下,返回内存引用将正常工作。否则,您将在内存释放期间遇到运行时异常(CLR总是尝试使用CoTaskMemFree来释放返回的内存)。我认为最好的是第一种方式,这在PeterHuene的回答中有所描述。以上就是C#学习教程:C#marshallingdouble*fromC++DLL?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
