Re: Pinning Pointers with __pin in Managed C++

Tech-Archive recommends: Speed Up your PC by fixing your registry



Hexar Anderson wrote:
"Ronald Laeremans [MSFT]" wrote:

For this situation you cannot use pinned pointers (which are only legal on the stack) but you should use a pinning handle. Create a GCHandle for each reference, call the GCHandle Alloc member 2 parameter overload with Pinned as the handle type. Put the handle in an array, create a second array (of IntPTR) and put the result of calling GCHandle::AddressOfPinnedObject into that and then you can pass that to native code.

Note that a design that needs this probably requires rethinking since keeping lots of pinnen objects (like an array of them) around for a long time isn't something to do too lightly.

Ronald Laeremans
Visual C++ team


Thanks for your response. That answers the question of whether or not I can use a __pin pointer in that way. I tried creating an array of GCHandles and then calling GCHandle::Alloc to create the pinned handles, but it didn't work, because I get an ArgumentException: "An instance with nonprimitive (non-blittable) members cannot be pinned." What I'm actually trying to do is a little more complicated, namely pin several 2D arrays of enums:

public __value enum MyEnum : unsigned char { ValueOne = 1, ValueTwo = 2};

public MyFunc()
{
Array* array __gc[] = new Array*[numObjects];
GCHandle pinners __gc[] = new GCHandle[numObjects];
vector<char*> v;
for (int i = 0; i < numObjects; i++)
{
  MyEnum e __gc[,] = new MyEnum[10, 10];
  array[i] = e;
  pinners[i] = GCHandle::Alloc(__box(e[0, 0]), GCHandleType::Pinned);
  v.push_back(static_cast<char*>(pinners[i].AddressOfPinnedObject()));
}
UnmanagedFunction(v);
// Omitted: Also call GCHandle.Free on the handles
}

I noticed also, that you cannot even create a GCHandle (pinned) on a single enum of any kind. That seems really strange to me. Is there any way to pass an array of 2D arrays of value-enums to unmanaged code?
You don't need to pin enums or other value types, they are always allocated inline, for these it is enough that you pin the array containing them.

I hope that is better news. :-)

Ronald
.



Relevant Pages

  • Re: Pinning Pointers with __pin in Managed C++
    ... call the GCHandle Alloc member 2 parameter overload with ... Put the handle in an array, ... namely pin several 2D arrays of enums: ...
    (microsoft.public.dotnet.languages.vc)
  • Re: Garbage collectable pinned arrays!
    ... When testArrayLength reaches 1024 elements you will see a big jump in the cost of the allocation. ... per element as a function of the array length. ... GCHandle h = GCHandle.Alloc; ... It makes no sense to post incomplete code snips, if you want to illustrate an issue post the whole code, so please give us the complete sample. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Garbage collectable pinned arrays!
    ... When testArrayLength reaches 1024 elements you will see a big jump in the cost of the allocation. ... per element as a function of the array length. ... Then add a second series to the chart: ... GCHandle h = GCHandle.Alloc; ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Convert from managed byte[] to void* and back to byte[] again
    ... You can use GCHandle to pin the array and retreive the pointer. ...
    (microsoft.public.dotnet.general)