Re: Pinning Pointers with __pin in Managed C++

Tech-Archive recommends: Fix windows errors by optimizing your registry



"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?
.



Relevant Pages

  • Re: Pinning Pointers with __pin in Managed C++
    ... 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 and put the result of calling GCHandle::AddressOfPinnedObject into that and then you can pass that to native code. ... use a __pin pointer in that way. ...
    (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)