2

I have a CLR class library in c++:

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);
    };
}

I am using this class as a reference in a WPF project:

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

Now I want to call the Train() method (in WPF) from that class and pass in some arguments. I have a problem to pass the first two parameters (pointers) to the method. My current code in 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);

I get the following error in C#:

enter image description here

Can anybody explain me how to pass an C# array to a c++ class library method?

1

2 Answers 2

2

As your ANN_FF_BP is a ref class and thus a CLR type it's better to pass .NET arrays to the C++/CLI method and do the hardwork there. This way you don't have to declare your C# code as unsafe what would be necessary here if you used pointers in C#.

This should work:

*.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);
}

To protect the arrays from being moved around in memory by the garbage-collector you need to use the 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.

Sign up to request clarification or add additional context in comments.

1 Comment

@EmirAhmetović you've also deserved a thank you because it is a really high quality question that contains all relevant information so it wasn't difficult I know it's relative ;-) to answer it. Keep it that way ;-]
1

If you wonder how the solution in unsafe C# looks:

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

1 Comment

I think it'd be a good idea if you could extend the example by wrapping it in a method with the unsafe keyword so that it's clear that it's necessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.