error C2664: 'innercppclass::getnum' : cannot convert parameter 1 from 'float' to 'float &'
An object from the gc heap (a dereferenced gc pointer) cannot be converted to a native reference
You forgot to document the error you're dealing with, this is what you saw. This is entirely by design and fundamental to the way managed code works.
The float% argument of the managed function can be an interior pointer to a managed object, like the field of a ref class. The float& reference will be a raw unmanaged pointer at runtime, pointing to the float value. Which allows the callee to update the value. Both are just plain pointers at runtime, the only difference is that the garbage collector can see the interior pointer but not the unmanaged pointer. The jitter tells it where to look for the managed pointer, no such help for the native C++ function since it wasn't jitted.
So assigning the unmanaged pointer with the interior pointer value would be possible. However, something very nasty happens when the garbage collector runs while the native code is running. Note that a GC can occur when other threads in the program allocate memory. One important thing the GC does is compact the heap, it moves managed objects as part of the collection. A very desirable trait, it gets rid of the holes in the heap and makes managed code fast by improving locality of reference. Trouble is, the native code is holding a pointer to where that float used to be before it got moved. And if it writes through the pointer, updating the float value, it will corrupt the GC heap.
There isn't any way that the GC can stop the native code from doing this, it doesn't know where the pointer value is located in memory so it cannot update it. No such trouble with the interior pointer but an unsolvable problem for the native reference.
So the compiler complains, it can't possibly generate code that won't crash your program sooner or later (usually later) with completely undiagnosable heap damage. You already found the workaround, you need to generate the pointer from a storage location that is not the GC heap. The stack is fine, local variables never move:
void Managed::getnum(float% num) {
float temp;
innercppclass::getnum(temp);
num = temp;
}
Otherwise the kind of code you'd write as well when you turn void getnum(float%) into float getnum(). Or more typically in managed code, a property getter:
property float num {
float get() {
float temp;
innercppclass::getnum(temp);
return temp;
}
}
Nothing much else you can do about it, it is a very fundamental restriction.