将 C# 数组传递给 C++ 方法

Pass a c# array to a c++ method

我有一个 C++ 中的 CLR class 库:

namespace ANN_Lib {

    public ref class ANN_FF_BP
    {
    private:
        int neurons;
        int inputs;
        int outputs;

        double **wi;
        double *wl;

    public:
        ANN_FF_BP(int neurons, int inputs, int outputs);

        void Train(double **p, double *t, int pairsCount, int epochs, double goal);
    };
}

我正在使用这个 class 作为 WPF 项目中的参考:

ANN_FF_BP neuralNetwork = new ANN_FF_BP(neurons, inputs, outputs);

现在我想从 class 调用 Train() 方法(在 WPF 中)并传入一些参数。我在将前两个参数(指针)传递给该方法时遇到问题。我当前的 C# 代码:

ANN_FF_BP neuralNetwork = new ANN_FF_BP(neurons, inputs, outputs);
double[,] P = new double[3, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 } };
double[] T = new double[] { 2, 4, 6 };
neuralNetwork.Train(P, T, 3, 20, 0.01);

我在 C# 中遇到以下错误:

任何人都可以向我解释如何将 C# 数组传递给 C++ class 库方法吗?

由于您的 ANN_FF_BPref class,因此是 CLR 类型,因此最好将 .NET 数组传递给 C++/CLI 方法并执行 努力那里。这样你就不必将你的 C# 代码声明为 unsafe 如果你在 C#.

中使用指针,那么这里是必需的

这应该有效:

*.h:

void Train(cli::array<double, 2>^ ps, cli::array<double>^ ts, int pairsCount, int epochs, double goal);

*.cpp:

void ClrClass::Train(cli::array<double, 2>^ ps, cli::array<double>^ ts, int pairsCount, int epochs, double goal) {

    // pin pointer to first element in ps
    pin_ptr<double> _ps = &ps[0,0];   
    double* p = _ps;

    // pin pointer to first element in ts
    pin_ptr<double> _ts = &ts[0];
    double* t = _ts;

    // Now with the two arrays being pinned you can call you native method.
    NativeClass::Train((double**)p, t, pairsCount, epochs, goal);
}

为了防止数组在内存中被垃圾收集器移动,你需要使用 pin_ptr:

A pinning pointer is an interior pointer that prevents the object pointed to from moving on the garbage-collected heap. That is, the value of a pinning pointer is not changed by the common language runtime. This is required when you pass the address of a managed class to an unmanaged function so that the address will not change unexpectedly during resolution of the unmanaged function call.

如果您想知道不安全 C# 中的解决方案看起来如何:

unsafe{
    fixed(double* ptr1 = &P[0,0])
    fixed(double* ptr2 = &T[0])
    {
        neuralNetwork.Train(ptr1, ptr2, 3, 20, 0.01);
    }
}