keyongtech


  keyongtech > dotnet.languages.* > dotnet.languages.vc

 #1  
02-29-08, 03:53 PM
Dilip
What is the best way to get a void* out of System.Object^?

Right now this is the way we go:

MyRefClass^ myreftype = ; // from somewhere
void* opaqueObj =
GCHandle::ToIntPtr(GCHandle::Alloc(myreftype)).ToP ointer();

when we unpack:

void* p = //........
GCHandle ourWrapper = GCHandle::FromIntPtr(safe_cast<IntPtr>(p));
MyRefClass^ ourObject = ourWrapper.Target;

I am wondering if I can eliminate GCHandle from the picture and get to
what I want? There is a deeper problem w.r.t passing GCHandle between
appdomains and I was wondering if there is a simple out of this mess.
 #2  
02-29-08, 05:06 PM
Tamas Demjen
Dilip wrote:
> What is the best way to get a void* out of System.Object^?


For what reason? If you need to pass the address of a managed object to
unmanaged code, you must pin it.

You can use pin_ptr<>, or if it's absolutely necessary,
GCHandle::Allocate with GCHandleType::Pinned passed to it.

If you don't pin the object, its address is free to change at any moment.

Tom
 #3  
02-29-08, 09:46 PM
Dilip
On Feb 29, 12:06 pm, Tamas Demjen <tdem> wrote:
> Dilip wrote:
> > What is the best way to get a void* out of System.Object^?

>
> For what reason? If you need to pass the address of a managed object to
> unmanaged code, you must pin it.


Tamas, I suspected that I would have to pin it. In my case I have
some code (lets call it 'rude_code' so that I can refer back to it
later) running on a secondary (non-default) appdomain that registers a
callback with unmanaged code. While registering the callback we have
to pass in the address of a managed object as a void*. When the
callback happens I get back the same void* which I have to break apart
and retrieve the System.Object^ type. When I have a GCHandle one of
the steps involved in breaking apart a void* is calling
GCHandle::FromIntPtr().

However the problem is I get a "GCHandle cannot be passed across
appdomains" exception on the FromIntPtr call, whenever rude_code is
made to run on the secondary appdomain. If I run rude_code in the
default appdomain everything works just fine!

Thats why I thought I'd circumvent the issue by not using a GCHandle
at all while converting a System.Object^ to a void* and still be able
to run rude_code in a secondary appdomain.

At this point my questions are mostly academic since I was forced to
back out this dual appdomain approach for lack of time but I am still
curious to know why I got that exception.

When unmanaged code calls back into managed code doesn't it know which
appdomain to select to execute?
 #4  
02-29-08, 10:07 PM
Jeroen Mostert
Dilip wrote:
[..]
>
> However the problem is I get a "GCHandle cannot be passed across
> appdomains" exception on the FromIntPtr call, whenever rude_code is
> made to run on the secondary appdomain. If I run rude_code in the
> default appdomain everything works just fine!
>
> Thats why I thought I'd circumvent the issue by not using a GCHandle
> at all while converting a System.Object^ to a void* and still be able
> to run rude_code in a secondary appdomain.
>

That will not work. You *must* either allocate a GCHandle or pin the object,
otherwise the object is eligible for garbage collection.

You can't really "convert" a managed reference to an unmanaged pointer. You
can only temporarily create unmanaged pointers to managed objects.

> At this point my questions are mostly academic since I was forced to
> back out this dual appdomain approach for lack of time but I am still
> curious to know why I got that exception.
>
> When unmanaged code calls back into managed code doesn't it know which
> appdomain to select to execute?


In general, no, it doesn't -- you must use delegates for that. See
http://lambert.geek.nz/2007/05/29/un...main-callback/
 #5  
03-01-08, 01:41 AM
Dilip
On Feb 29, 5:07 pm, Jeroen Mostert <jmost> wrote:
> Dilip wrote:
> > Thats why I thought I'd circumvent the issue by not using a GCHandle
> > at all while converting a System.Object^ to a void* and still be able
> > to run rude_code in a secondary appdomain.

>
> That will not work. You *must* either allocate a GCHandle or pin the object,
> otherwise the object is eligible for garbage collection.


Gotcha Jeroen. I understand perfectly. FWIW, the code I inherited
just allocates a GCHandle and never pins it (using that Pinned
enumeration Tamas was talking about elsethread). I wonder how it has
been working all these years.

> You can't really "convert" a managed reference to an unmanaged pointer. You
> can only temporarily create unmanaged pointers to managed objects.
>
> > At this point my questions are mostly academic since I was forced to
> > back out this dual appdomain approach for lack of time but I am still
> > curious to know why I got that exception.

>
> > When unmanaged code calls back into managed code doesn't it know which
> > appdomain to select to execute?

>
> In general, no, it doesn't -- you must use delegates for that. Seehttp://lambert.geek.nz/2007/05/29/unmanaged-appdomain-callback/


Wow! Thats *exactly* what I ran into. Thanks Jeroen! How in the
world do you guys keep track of things like this??!! Seems like an
obscure problem to me...
 #6  
03-01-08, 09:46 AM
Jeroen Mostert
Dilip wrote:
> On Feb 29, 5:07 pm, Jeroen Mostert <jmost> wrote:
>> Dilip wrote:
>>> Thats why I thought I'd circumvent the issue by not using a GCHandle
>>> at all while converting a System.Object^ to a void* and still be able
>>> to run rude_code in a secondary appdomain.

>> That will not work. You *must* either allocate a GCHandle or pin the object,
>> otherwise the object is eligible for garbage collection.

>
> Gotcha Jeroen. I understand perfectly. FWIW, the code I inherited
> just allocates a GCHandle and never pins it (using that Pinned
> enumeration Tamas was talking about elsethread). I wonder how it has
> been working all these years.
>

Allocating a GCHandle will prevent GC as well. Pinning is only necessary if
you need the address of the object in unmanaged code. The code fragment you
showed doesn't: it actually retrieves opaque handles when it calls
..ToIntPtr(), not direct pointers. These handles can be converted back and
passed to managed code for as long as the GCHandle remains allocated.

> Wow! Thats *exactly* what I ran into. Thanks Jeroen! How in the
> world do you guys keep track of things like this??!! Seems like an
> obscure problem to me...


I didn't keep track; I've never seen this problem before (I've worked with
callbacks into unmanaged code and separate appdomains, just not in
combination). I simply googled for "delegate unmanaged appdomain". The
supplied site is the first hit. Knowing that delegates should probably be
involved is a guess, granted.

Now that I have seen it, however, I will keep track, in case anyone around
me ever runs into it. Repeat until all-knowing! :-)
Similar Threads
How to convert System::String* (or System::Void) to void** in MC++?

Hy! I have written a MC++ wrapper DLL file for use in a C# project. This wrapper DLL is built on a C DLL. I have the following functions in the C DLL: int First(char* a1,...

Convert void pointer to System.Object

Hopefully someone can help me out with this; if what I'm asking is even possible. My basic question is how can I convert a void * into an Object and then later convert it...

Converting a BSTR to System::Object, How???

Hi I am using mixed mode C++ and I wonder.... How could I convert a BSTR to a System::Object* type Cheers,

Method not found: Void System.EventHandler..ctor(System.Object, IntPtr).

Hi! While trying to run my first web application using Microsost Visual Studio .net I came up with the following error: Method not found: Void...


All times are GMT. The time now is 07:04 PM. | Privacy Policy