使用CLI将c#双精度数组传递给c++函数
本文关键字:c++ 函数 数组 CLI 双精度 使用 | 更新日期: 2023-09-27 18:04:34
是的,需要做的事情听起来很简单,但事实证明这是一个真正的痛苦。
我在 c# 中有一些GUI代码(注意我以前从未使用过c#,但熟悉语法),我有 c++ 代码,使用CLI与之交互。
在c#中,我想创建一个双精度数组,并将其发送到我的c++代码中。我使用下面的代码作为传递数组的方法,并且这是单独执行的。所以在c#中,我将一个double[]数组传递给这个函数。
public ref class KernelWrapper
{
public:
static void ImageNoiseFilter(System::IntPtr imageData, int imageWidth, int imageHeight, array<double>^ values);
我应该使用什么参数类型来从c++端检索这个数组?
我试过:
MyFunction(double values[]){}
MyFunction(double* values){}
MyFunction(array<double>^ values){}
但是没有编译,通常最后一个会显示"array is not a template"的信息,而
Error 1 error C2664: 'RunImageNoiseFilterKernel' : cannot convert parameter 4 from 'cli::array<Type> ^' to 'double *'
如果有任何关于如何做到这一点的建议,我将不胜感激。
为了可读性,我在这里更新了代码
<标题> . cpp文件:void Bangor::KernelWrapper::ImageNoiseFilter(System::IntPtr imageData, int imageWidth, int imageHeight, pin_ptr<double> pval){
RunImageNoiseFilterKernel((Format24bppRgb*)((int)imageData), imageWidth, imageHeight); //If parameter would work, 4th argument would also be passed into this.
}
<标题> c#代码: double[] randomValues = new double[ARRAY_LENGTH]; //Array of random numbers
KernelWrapper.ImageNoiseFilter(ptr, image.Width, image.Height, randomValues);
错误包括:
Error 1 error C3824: 'cli::pin_ptr<Type>': this type cannot appear in this context (function parameter, return type, or a static member)
Error 3 The best overloaded method match for 'Bangor.KernelWrapper.ImageNoiseFilter(System.IntPtr, int, int, double*)' has some invalid arguments
Error 4 Argument 4: cannot convert from 'double[]' to 'double*'
标题>标题>
您应该使用pin_ptr<>类将托管数组转换为双精度*。它固定数组,所以垃圾收集器不能在本机函数执行和访问数组数据时移动它。
#include <vcclr.h> // Declares cli::pin_ptr<>
using namespace cli;
#pragma managed(push, off)
# include "unmanagedstuff.h" // Declaration of MyFunction here
#pragma managed(pop)
...
pin_ptr<double> pvalues = &values[0];
MyFunction(pvalues, values->Length);
假设MyFunction()也需要知道数组的大小,所以我添加了一个额外的参数来传递数组的大小。不这样做是致命的,您的本机代码可能会破坏托管堆的完整性。请注意,只有当pvalues在作用域中时,数组才会保持固定,因此MyFunction()不存储传入的指针是很重要的。如果是这种情况,那么必须复制数组。
好吧,所以我的大多数尝试都失败了;可能是因为我做错了:P,但这里有一个解决方案确实有效。
进口:
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Linq;
在c#文件中,我创建了一个数组: float[] randomValues = new float[ARRAY_LENGTH]; //Array of random numbers
GCHandle handle = GCHandle.Alloc(randomValues, GCHandleType.Pinned);
var randPtr = handle.AddrOfPinnedObject();
KernelWrapper.ImageNoiseFilter(ptr, image.Width, image.Height, randPtr);
ImageNoiseFilter的定义为:
static void ImageNoiseFilter(System::IntPtr imageData, int imageWidth, int imageHeight, System::IntPtr randValPtr);
要在我的c++函数中获得一个浮点指针,我这样做:
void KernelWrapper::ImageNoiseFilter(System::IntPtr imageData, int imageWidth, int imageHeight, System::IntPtr randValues){
RunImageNoiseFilterKernel((Format24bppRgb*)((int)imageData), imageWidth, imageHeight, (float*) ((int) randValues));
}
所有这些似乎都很好:),这种方法有多好或安全我不知道,所以任何读到这篇文章的人都不应该认为这是"正确"的方法,它只是有效的。