Itay Gal Itay Gal - 11 months ago 61
C++ Question

C++\CLI - How to convert UInt64^% to unsigned long long*

I have a C++ function that calculates a buffer size:

CalcBuffer(unsigned long long* bufferSize);

I want to pass this result into a different function later in my C# code.
My C++\CLI Wrapper looks like this:

CalcBufferWrapper([Out] UInt64^% bufferSize){

But I'm getting this error:

argument of type "System::UInt64 ^" is incompatible with
parameter of type "unsigned long long *".

Obviously, I need to use a different type, but which type?

Answer Source

UInt64^% doesn't mean what you think it does. The ^ hat should only be used on reference types, UInt64 is a value type. Doing this is wrong about 99% of the time but the C++/CLI compiler accepts it anyway and interprets it as "reference to a boxed 64-bit unsigned integer". A boxing conversion turns a value into an object, implements the famous illusion that value types also derive from System::Object.

Which certainly is not compatible with an unsigned long long*. Do review your code to ensure that you don't accidentally use the ^ hat inappropriately elsewhere. It is a drastic processor cycles sink, makes code about an order of magnitude slower than it needs to be.

You have to stop using the hat. And deal with the possible reason you added it, that UInt64 might be a field of a managed object. Which might be moved by the garbage collector while the native code is running. That would be utterly disastrous (the native code now corrupts the heap) so the compiler won't allow it. You have to provide a stable copy of the value that cannot move:

void CalcBufferWrapper(UInt64% bufferSize) {
     auto size = bufferSize;      // Values on the stack don't move
     bufferSize = size;

Or much better, no need at all give the wrapper the exact same signature as the wrapped function:

UInt64 CalcBufferWrapper() {
   unsigned long long size;
   return size;

Some odds that this should be a property as well.