5

Alright, I know how you normally would declare a pointer:

void SomeFunction(array<float> ^managedArray)
{
  pin_ptr<float> managedArrayPtr = &managedArray[0];
}

This works fine except when managedArray contains no elements. In that case, it throws an IndexOutOfRangeException.

In C# you can do this:

void SomeFunction(float[] managedArray)
{
  fixed (float* managedArrayPtr = managedArray)
  {
  }
}

Which does no memory access and works even if managedArray is empty. Do I really have to check for the number of elements everywhere I use pointers to managed arrays or does C++/CLI have a way to do it like C#? It should be using the 'lea' instruction in ASM which does no memory access.

Any help is greatly appreciated!

user425451
  • 61
  • 1
  • 3

2 Answers2

3

There isn't much point in trying to read from the array when it is empty. Just check for that:

void SomeFunction(array<float> ^managedArray)
{
    if (managedArray->Length > 0) {
        pin_ptr<float> managedArrayPtr = managedArray;
        //etc...
    }
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • You're right, but it's annoying to check that everywhere. I was hoping for a shorthand since something like this is used very often in pointer languages. Anyways I'll use this. – user425451 Aug 19 '10 at 18:34
  • *Everywhere*? You need to use this kind of code sparingly, pinning isn't healthy for the garbage collector. – Hans Passant Aug 19 '10 at 18:38
  • 2
    I'm wrapping a native library and I do indeed use it everywhere. Sure, it might not really be 'everywhere' generally, but while wrapping this library, yes everywhere. – user425451 Aug 19 '10 at 19:07
1

Good question. Unfortunately I am not that familiar with C++/CLI. I do know that you can do the pinning manually using the GCHandle struct and will work on empty arrays. It is not as elegant as using pin_ptr though.

void SomeFunction(array<float> ^managedArray) 
{ 
 GCHandle handle = GCHandle::Alloc(managedArray, GCHandleType::Pinned);
 try 
 {
  float* ptr = (float*)(void*)handle.AddrOfPinnedObject();
 }
 finally
 {
  handle.Free();
 }
} 
Brian Gideon
  • 47,849
  • 13
  • 107
  • 150
  • But then I might as well just check the length. I was hoping for a quick way, like an operator or something. – user425451 Aug 19 '10 at 17:50
  • Yeah, checking the length is probably the way to go. I googled quite a bit I could not find an elegant solution either. – Brian Gideon Aug 19 '10 at 18:07