mr-ma
mr-ma

Reputation: 199

Passing pointer-to-pointer to c++ class library from c#

I have legacy c library and exported it all in a c++ class library. So far, I have problem with passing arguments of type double** which simply is an out 2D array. Here is my c++ method signature:

public:  int  GetVariableValues(double **time_values) {
return LegacyGetVariableValues(time_values);}

And here is my c# client call:

double[][] a;
Legacy.GetVariableValues(a);

However it does not work and I get type errors. Anyone knows how to pass **(out) of course without using unsafe tag in C# client.

Upvotes: 0

Views: 315

Answers (1)

greenboxal
greenboxal

Reputation: 469

You don't need the C++/CLI library is this case, pinning a multidimensional array is harder than just pinning a one-dimensional array as you need to pin the inner arrays manually. If you do it with C#, the compiler does it automatically for you.

With C#, you can do this:

[DllImport('legacylibrary.dll')]
public static extern int LegacyGetVariableValues(double[][] timeValues);

For further reading, check http://msdn.microsoft.com/en-us/library/fzhhdwae(v=vs.110).aspx

Edit:

As you need the C++/CLI layer, you need to do something like this:

ref class Legacy {
    public:
    int GetVariableValues(array<array<double> ^> ^values) {
        array<GCHandle> ^handles = gcnew array<GCHandle>(values->Length);
        double **valuesPtr = calloc(sizeof(double *), values->Length);
        int result;

        for (int i = 0; i < values->Length; i++) {
            handles[i] = GCHandle::Alloc(values[i]);
            valuesPtr[i] = (double *)GCHandle::ToIntPtr(handles[i]).GetPointer();
        }

        result = LegacyGetVariableValues(valuesPtr);

        for (int i = 0; i < values->Length; i++) {
            handles[i].Free();
        }

        return result;
    }
}

PS: Don't know if the syntax is completely correct as I don't write C++/CLI in a long time.

Upvotes: 2

Related Questions