teodron
teodron

Reputation: 1438

C++/CLI from tracking reference to (native) reference - wrapping

I need a C# interface to call some native C++ code via the CLI dialect. The C# interface uses the out attribute specifier in front of the required parameters. That translates to a % tracking reference in C++/CLI.

The method I has the following signature and body (it is calling another native method to do the job):

virtual void __clrcall GetMetrics(unsigned int %width, unsigned int %height, unsigned int %colourDepth, int %left, int %top) sealed
{
    mRenderWindow->getMetrics(width, height, colourDepth, left, top);
}

Now the code won't compile because of a few compile time errors (all being related to not being able to convert parameter 1 from 'unsigned int' to 'unsigned int &').

As a modest C++ programmer, to me CLI is looking like Dutch to a German speaker. What can be done to make this wrapper work properly in CLI?

Upvotes: 0

Views: 1376

Answers (3)

Rio Wing
Rio Wing

Reputation: 672

You can use pin_ptr so that 'width' doesn't move when native code changes it. The managed side suffers from pin_ptr, but I don't think you can get around that if you want native code directly access it without 'w'.

virtual void __clrcall GetMetrics(unsigned int %width, unsigned int %height, unsigned int %colourDepth, int %left, int %top) sealed
        {
            pin_ptr<unsigned int> pw = &width; //do the same for height
            mRenderWindow->getMetrics(*pw, h, c, l, t);
        }

Upvotes: 0

teodron
teodron

Reputation: 1438

Like it was also suggested in a deleted answer, I did the obvious and used local variables to pass the relevant values around:

 virtual void __clrcall GetMetrics(unsigned int %width, unsigned int %height, unsigned int %colourDepth, int %left, int %top) sealed
        {
            unsigned int w = width, h = height, c = colourDepth;
            int l = left, t = top;
            mRenderWindow->getMetrics(w, h, c, l, t);
            width = w; height = h; colourDepth = c; left = l; top = t;
        }

It was a bit obvious since the rather intuitive mechanism of tracked references: they're affected by the garbage collector's work and are not really that static/constant as normal &references when they're prone to be put somewhere else in memory. Thus this is the only way reliable enough to overcome the issue. Thanks to the initial answer.

Upvotes: 2

Shahin Dohan
Shahin Dohan

Reputation: 6922

If your parameters use 'out' on the C# side, you need to define your C++/CLI parameters like this: [Out] unsigned int ^%width

Here's an example:

virtual void __clrcall GetMetrics([Out] unsigned int ^%width)
{
    width = gcnew UInt32(42);
}

Then on your C# side, you'll get back 42:

ValueType vt;
var res = cppClass.GetMetrics(out vt);
//vt == 42

In order to use the [Out] parameter on the C++/CLI side you'll need to include:

using namespace System::Runtime::InteropServices;

Hope this helps!

Upvotes: 0

Related Questions