views:

529

answers:

2

Hello all, I have a 3rd party collection of .h files along with the .lib files that go with them. I am wrapping those native C++ files with a C++/CLI wrapper and making final calls from C#. I have an issue when I call methods that expect a reference to be passed in where the value is not getting changed in my wrapper unless I explicitly change it.

My C++/CLI wrapper code currently looks like this:

bool get_testInt16(int16% testInt16)
{
   int16* t = static_cast<int16*>(GCHandle::ToIntPtr(GCHandle::Alloc(testInt16)).ToPointer());
   bool b = m_NativeCMTY_TestData->get_testInt16(*t);
   testInt16 = *t;
   return b;
};

And the corresponding native C++ code looks like:

bool get_testInt16(int16 &testInt16);

I figure there's gotta be a better way, but maybe not? Let just say I'm HOPING there's a better way!

+3  A: 

An option would be to do:

bool get_testInt16(int16% testInt16)
{
   int16 t = testInt16;
   bool b = m_NativeCMTY_TestData->get_testInt16(t);
   testInt16 = t;
   return b;
};

So you simply create a local native variable and avoid the huge cast and .NET pointer stuff.

rstevens
A: 

any reason you're not using pinning pointers instead of GCHandle::ToIntPtr(GCHandle::Alloc(testInt16)).ToPointer()?

Also pinning the referenced value like this is too late.

If the reference is to a stack value it is unneeded, if it is a reference to an instance field then the calling code should really pin the object (though this is a messy leakage of unmanaged semntics into managed code it at least makes the behaviour of the method clear.

Since the ref parameter is so small it would make sense to just avoid all the pinning entirely and create a temporary one on the stack, pass that through to the unmanaged function and then write it back to the original.

bool get_testInt16(int16% testInt16)
{
   int16 temp = testInt16;
   bool b = m_NativeCMTY_TestData->get_testInt16(temp);
   testInt16 = temp;
   return b;
};
ShuggyCoUk
I suppose what I was really trying to avoid was the explicit assignment back to argument 'testInt16'. The only real reason I was doing the pinning was an attempt to pass something directly into the native call that would allow me to avoid this explicit assignment.
TomO
I would say that the overhead and complexity of the pinning is way more effort that just doing a copy, certainly for anything primitive sized...
ShuggyCoUk