pin_ptr global to a class

  • Thread starter Thread starter _iycrd
  • Start date Start date
I

_iycrd

Is there an easy way to pin a pointer that is a member of a class, and
leave that pointer pinned for the duration of the class's existence?
The pointer would presumably be pinned inside the class's constructor,
but maintain the pin after exiting the constructor.

The syntax, at least under C++/CLI, seems to require simultaneous
declaration and pinning. Any way around that?
 
Is there an easy way to pin a pointer that is a member of a class, and
leave that pointer pinned for the duration of the class's existence?
The pointer would presumably be pinned inside the class's constructor,
but maintain the pin after exiting the constructor.

The syntax, at least under C++/CLI, seems to require simultaneous
declaration and pinning. Any way around that?

if you try to make a pinnend pointer a data member of a class, you get
compiler error C3831: pinnend pointer cannot be a data member or a return
value.

I think this is impossible. If I am wrong someone please correct me, but I
think the reason is this:
If you could do this and pin a member in the constructor, your object would
be be collectible or movable by the GC.

pinning any class member prevents the object from being moved by the GC.
this means that all instances of your class would be fxed in the managed
heap, leading to serious heap fragmentation, which is not the intention.

I am also not sure what would happen when you would try to delete the object.
the GC cannot manage you object as long as the member is pinned. since the
finalizer is called by the GC, it would never be able to finalize your
object??

Anyway, you should only pin data for temporary internal or external use, and
for as short a time as possible to prevent heap fragmentation.

--

Kind regards,
Bruno.
(e-mail address removed)
Remove only "_nos_pam"
 
_iycrd said:
Is there an easy way to pin a pointer that is a member of a class, and
leave that pointer pinned for the duration of the class's existence?
The pointer would presumably be pinned inside the class's constructor,
but maintain the pin after exiting the constructor.

There are a few (very rare) situations when pin_ptr doesn't work,
because it uses the stack syntax, and it auto-releases the pin when your
function exits (or when the pinned pointer goes out of scope). Read
Ronald Laeremans' first answer in this thread to learn how to pin
pointers manually and keep them pinned using a pinning handle:

http://tinyurl.com/o9qkp

With this techinque, you can manually pin an object, and you decide when
you wish to release the pin.

Whether this makes sense in your case is a different story. I would
personally avoid doing it. The big problem with it is that pinned
objects can't be moved around in the memory, and therefore your managed
heap will get fragmented if you keep a lot of objects pinned for a long
time. Keep this in mind, and consider pinning the pointer for only a
brief period of time while an unmanaged function is being executed.
There is a reason why the pin_ptr uses a stack syntax. If you need
something pinned indefinitely, you should rethink your design. You could
just copy your managed data into an unmanaged buffer, which doesn't
require pinning.

Tom
 
[pinning handle]
http://tinyurl.com/o9qkp
The big problem with it is that pinned
objects can't be moved around in the memory, and therefore your managed
heap will get fragmented if you keep a lot of objects pinned for a long
time. Keep this in mind, and consider pinning the pointer for only a
brief period of time while an unmanaged function is being executed.
There is a reason why the pin_ptr uses a stack syntax. If you need
something pinned indefinitely, you should rethink your design. You could
just copy your managed data into an unmanaged buffer, which doesn't
require pinning.

Thanks for the info, Tom. I was not familiear with pinning handles.
Is this still relevant with C++/CLI?

In this case I am trying to come up with a good design for wrapping a
native DLL in a C++ class for access by C#. There will be one object,
and it will be alloc'd at the start of the program, freed at the end,
so I don't anticipate much fragmentation.

I'm having trouble with the approach I was trying to take (weird
runtime error, I'll post about that separately). PInvoke seems too
complex. I can't wrap the unmanaged code directly via C++/CLI (can't
embed unmanaged data in the ref class).

So I've ended up with an C++/CLI #pragma unmanaged shell class talking
to the native DLL, with a managed C++/CLI wrapping that. Ugly. I'm
looking for alternatives.
 
_iycrd said:
Thanks for the info, Tom. I was not familiear with pinning handles.
Is this still relevant with C++/CLI?

I'm having trouble with the approach I was trying to take (weird
runtime error, I'll post about that separately). PInvoke seems too
complex. I can't wrap the unmanaged code directly via C++/CLI (can't
embed unmanaged data in the ref class).

You can use IJW instead of PInvoke. A ref class can hold unmanaged
pointers, so you can do this:

class UC
{
};

ref class MC
{
public:
MC() : unmanaged(new UC) { }
~MC() { delete unmanaged; }
private:
UC * unmanaged;
};

You just have to create "unmanaged" with new, and delete it from the
destructor, and ensure that the C# program is calling Dispose on it:

MC mc = new MC();
[...]
mc.Dispose();

Tom
 
_iycrd wrote:
In this case I am trying to come up with a good design for wrapping a
native DLL in a C++ class for access by C#. There will be one object,
and it will be alloc'd at the start of the program, freed at the end,
so I don't anticipate much fragmentation.

I'm having trouble with the approach I was trying to take (weird
runtime error, I'll post about that separately). PInvoke seems too
complex. I can't wrap the unmanaged code directly via C++/CLI (can't
embed unmanaged data in the ref class).

The usual idiom is :

ref class wrapper
{
public:
wrapper()
{
m_unmanaged_object=new unmanagedobject();
}
~wrapper()
{
m_unmanaged_object=new unmanagedobject();
}

private:
unmanagedobject* m_unmanaged_object;
};

This way, the native object is created by the native runtime and is created
outside of the GC heap. Therefore:
- the object is "pinned" (it doesn't move around in memory)
- it doesn't disturb the GC by fragmenting the GC heap.

Arnaud
MVP - VC
 
Arnaud said:
_iycrd wrote:


The usual idiom is :

ref class wrapper
{
public:
wrapper()
{
m_unmanaged_object=new unmanagedobject();
}
~wrapper()
{
m_unmanaged_object=new unmanagedobject();

I'm sure you meant:

delete m_unmanaged_object;

-cd
 
Back
Top