By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,127 Members | 1,343 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,127 IT Pros & Developers. It's quick & easy.

What is proper way to pass a managed object into unmanaged code?

P: n/a
I would greatly appreciate some help on passing managed object into unmanaged
code.
I need to pass a reference (address of) of a managed class into unmanaged
code (written by a thrid party). The 3rd party unmanaged DLL will pass this
reference into standard Win32 unmanaged static callback function in my code.
Inside this unmanaged callback function I need to cast this unmnaged pointer
that I have received from 3rd party back into the reference to a managed
class, so I could use member variables and functions of that managed class.

I do not have source code for the third party DLL, but our applicatin was
working perfectly fine with that thrid party DLL when it was built with all
unmanaged C++ code.

Here is my managed C++ class declaration inside Wrapper.h:

namespace MyNamespace
{
public ref class Wrapper
{
unsigned long m_hSource;
public:
Wrapper();
bool SetupCallback();
};
}

Here is code inside Wrapper.cpp

unsigned long __stdcall CallBackFunc(const void * pData, unsigned Context )
{
gcroot<eWCamera_Canon::CanonWrapper^cwThis;

// Here is the place in question for casting back into managed class

// use m_hSource to delegate to C# User Interface
}

bool MyNameSpace::Wrapper::SetupCallback()
{
unsigned int err;

// Registering callback with 3rd party DLL
err = RegisterCallback(CallBackFunc, this);
}
Dec 19 '07 #1
Share this Question
Share on Google+
9 Replies


P: n/a
"EdwardS" <Ed*****@discussions.microsoft.comwrote in message
news:CC**********************************@microsof t.com...
>I would greatly appreciate some help on passing managed object into
unmanaged
code.
I need to pass a reference (address of) of a managed class into unmanaged
code (written by a thrid party). The 3rd party unmanaged DLL will pass
this
reference into standard Win32 unmanaged static callback function in my
code.
Inside this unmanaged callback function I need to cast this unmnaged
pointer
that I have received from 3rd party back into the reference to a managed
class, so I could use member variables and functions of that managed
class.

It seems to me it would be easier to use gcroot to store a managed reference
in an unmanaged object which is passed through the callback mechanism. Then
in the callback, you can use the gcroot-held managed reference as usual.

Here's an example (namespace removed for clarity)...

class Wrapper
{
unsigned long m_hSource;

public:
gcroot<eWCamera_Canon::CanonWrapper^ManagedReferen ce;

Wrapper();
bool SetupCallback();
};

unsigned long __stdcall CallBackFunc(const void * pData, unsigned Context )
{
// Get the unmanaged wrapper pointer
Wrapper *pWrapper = (Wrapper *)pData;

// Use the wrapped managed object
pWrapper->ManagedReference->...
}

bool Wrapper::SetupCallback()
{
unsigned int err;

// Registering callback with 3rd party DLL
err = RegisterCallback(CallBackFunc, this);
}


Mark

--
Mark Salsbery
Microsoft MVP - Visual C++


>
I do not have source code for the third party DLL, but our applicatin was
working perfectly fine with that thrid party DLL when it was built with
all
unmanaged C++ code.

Here is my managed C++ class declaration inside Wrapper.h:

namespace MyNamespace
{
public ref class Wrapper
{
unsigned long m_hSource;
public:
Wrapper();
bool SetupCallback();
};
}

Here is code inside Wrapper.cpp

unsigned long __stdcall CallBackFunc(const void * pData, unsigned
Context )
{
gcroot<eWCamera_Canon::CanonWrapper^cwThis;

// Here is the place in question for casting back into managed class

// use m_hSource to delegate to C# User Interface
}

bool MyNameSpace::Wrapper::SetupCallback()
{
unsigned int err;

// Registering callback with 3rd party DLL
err = RegisterCallback(CallBackFunc, this);
}
Dec 19 '07 #2

P: n/a
Mark,
Thanks for reply, I just realized that while cleaning code for you, I did
not clean everything (<eWCamera_Canon::CanonWrapper^is actually
<MyNamespace::Wrapper^>, I think that created a lot of confusion. Could you
take a look at this code again, I greatly appreciate your help. Does it
change your response in anyway? In the following code Wrapper must be a
managed class, that is the whole point of my question - how to pass managed
object (pass itself) into unmanaged area and later be casted into the managed
type of itself, so that member methods of that managed class could be used
inside that unmanaged static callback function?

namespace MyNamespace
{
public ref class Wrapper
{
unsigned long m_hSource;
public:
Wrapper();
bool SetupCallback();
};
}

Here is code inside Wrapper.cpp

unsigned long __stdcall CallBackFunc(const void * pData, unsigned Context )
{
gcroot<MyNamespace::Wrapper^cwThis;

// Here is the place in question for casting back into managed class

// use m_hSource to delegate to C# User Interface
}

bool MyNamespace::Wrapper::SetupCallback()
{
unsigned int err;

// Registering callback with 3rd party DLL
err = RegisterCallback(CallBackFunc, this);
}
Dec 19 '07 #3

P: n/a
One more clarification to my code - inside Callback function, I would like to
cast Context which now holds the pointer to the managed object into
<MyNamespace::Wrapper^type. Origianly pointer was passed inside the
RegisterCallback function in MyNamespace::Wrapper::SetupCallback() method of
the <MyNamespace::Wrapper^class.

unsigned long __stdcall CallBackFunc(const void * pData, unsigned Context )
{
gcroot<MyNamespace::Wrapper^cwThis;

// Here is the place in question for casting Context back
// into managed class cwThis of type <MyNamespace::Wrapper^>

// use m_hSource to delegate to C# User Interface
// where m_hSource will do something with pData,
// or pData converted into m_hSource (that part does not matter)
}
"EdwardS" wrote:
Mark,
Thanks for reply, I just realized that while cleaning code for you, I did
not clean everything (<eWCamera_Canon::CanonWrapper^is actually
<MyNamespace::Wrapper^>, I think that created a lot of confusion. Could you
take a look at this code again, I greatly appreciate your help. Does it
change your response in anyway? In the following code Wrapper must be a
managed class, that is the whole point of my question - how to pass managed
object (pass itself) into unmanaged area and later be casted into the managed
type of itself, so that member methods of that managed class could be used
inside that unmanaged static callback function?

namespace MyNamespace
{
public ref class Wrapper
{
unsigned long m_hSource;
public:
Wrapper();
bool SetupCallback();
};
}

Here is code inside Wrapper.cpp

unsigned long __stdcall CallBackFunc(const void * pData, unsigned Context )
{
gcroot<MyNamespace::Wrapper^cwThis;

// Here is the place in question for casting back into managed class

// use m_hSource to delegate to C# User Interface
}

bool MyNamespace::Wrapper::SetupCallback()
{
unsigned int err;

// Registering callback with 3rd party DLL
err = RegisterCallback(CallBackFunc, this);
}
Dec 19 '07 #4

P: n/a
"EdwardS" <Ed*****@discussions.microsoft.comwrote in message
news:47**********************************@microsof t.com...
Mark,
Thanks for reply, I just realized that while cleaning code for you, I did
not clean everything (<eWCamera_Canon::CanonWrapper^is actually
<MyNamespace::Wrapper^>, I think that created a lot of confusion.
Yes - I wasn't quite sure what needed to be managed so I used what was there
to demonstrate the basic framework of what I was referring to :)
>Could you
take a look at this code again, I greatly appreciate your help. Does it
change your response in anyway? In the following code Wrapper must be a
managed class, that is the whole point of my question - how to pass
managed
object (pass itself) into unmanaged area and later be casted into the
managed
type of itself, so that member methods of that managed class could be used
inside that unmanaged static callback function?
You really can't do that. There's no way for the system to track the
managed reference once you pass it to unmanaged code. That's why I kind of
flipped the way you were attempting it so an unmanaged wrapper could go
through the unmanaged callback mechanism, carrying with it the managed
reference stored with gcroot.

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++

>
namespace MyNamespace
{
public ref class Wrapper
{
unsigned long m_hSource;
public:
Wrapper();
bool SetupCallback();
};
}

Here is code inside Wrapper.cpp

unsigned long __stdcall CallBackFunc(const void * pData, unsigned
Context )
{
gcroot<MyNamespace::Wrapper^cwThis;

// Here is the place in question for casting back into managed class

// use m_hSource to delegate to C# User Interface
}

bool MyNamespace::Wrapper::SetupCallback()
{
unsigned int err;

// Registering callback with 3rd party DLL
err = RegisterCallback(CallBackFunc, this);
}
Dec 19 '07 #5

P: n/a
"EdwardS" <Ed*****@discussions.microsoft.comwrote in message
news:F3**********************************@microsof t.com...
One more clarification to my code - inside Callback function, I would like
to
cast Context which now holds the pointer to the managed object into
<MyNamespace::Wrapper^type.

That won't work either. The only way you can pass a pointer to a managed
object to unmanaged code is with a pin_ptr. The problem is, a pin_ptr only
exists until it goes out of scope, and I don't think that's going to work
for this unmanaged callback scenario, since a pin_ptr would go out of scope
at the end of SetupCallback().

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++

>Origianly pointer was passed inside the
RegisterCallback function in MyNamespace::Wrapper::SetupCallback() method
of
the <MyNamespace::Wrapper^class.

unsigned long __stdcall CallBackFunc(const void * pData, unsigned
Context )
{
gcroot<MyNamespace::Wrapper^cwThis;

// Here is the place in question for casting Context back
// into managed class cwThis of type <MyNamespace::Wrapper^>

// use m_hSource to delegate to C# User Interface
// where m_hSource will do something with pData,
// or pData converted into m_hSource (that part does not matter)
}
"EdwardS" wrote:
>Mark,
Thanks for reply, I just realized that while cleaning code for you, I did
not clean everything (<eWCamera_Canon::CanonWrapper^is actually
<MyNamespace::Wrapper^>, I think that created a lot of confusion. Could
you
take a look at this code again, I greatly appreciate your help. Does it
change your response in anyway? In the following code Wrapper must be a
managed class, that is the whole point of my question - how to pass
managed
object (pass itself) into unmanaged area and later be casted into the
managed
type of itself, so that member methods of that managed class could be
used
inside that unmanaged static callback function?

namespace MyNamespace
{
public ref class Wrapper
{
unsigned long m_hSource;
public:
Wrapper();
bool SetupCallback();
};
}

Here is code inside Wrapper.cpp

unsigned long __stdcall CallBackFunc(const void * pData, unsigned
Context )
{
gcroot<MyNamespace::Wrapper^cwThis;

// Here is the place in question for casting back into managed class

// use m_hSource to delegate to C# User Interface
}

bool MyNamespace::Wrapper::SetupCallback()
{
unsigned int err;

// Registering callback with 3rd party DLL
err = RegisterCallback(CallBackFunc, this);
}
Dec 19 '07 #6

P: n/a
Thanks, Mark... I tried pin_ptr... I know... I thought that my scenario would
not work. I just wanted to make sure. I will try to figure out a work
around...
Thank you very much for your help.

"Mark Salsbery [MVP]" wrote:
"EdwardS" <Ed*****@discussions.microsoft.comwrote in message
news:F3**********************************@microsof t.com...
One more clarification to my code - inside Callback function, I would like
to
cast Context which now holds the pointer to the managed object into
<MyNamespace::Wrapper^type.


That won't work either. The only way you can pass a pointer to a managed
object to unmanaged code is with a pin_ptr. The problem is, a pin_ptr only
exists until it goes out of scope, and I don't think that's going to work
for this unmanaged callback scenario, since a pin_ptr would go out of scope
at the end of SetupCallback().

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++

Origianly pointer was passed inside the
RegisterCallback function in MyNamespace::Wrapper::SetupCallback() method
of
the <MyNamespace::Wrapper^class.

unsigned long __stdcall CallBackFunc(const void * pData, unsigned
Context )
{
gcroot<MyNamespace::Wrapper^cwThis;

// Here is the place in question for casting Context back
// into managed class cwThis of type <MyNamespace::Wrapper^>

// use m_hSource to delegate to C# User Interface
// where m_hSource will do something with pData,
// or pData converted into m_hSource (that part does not matter)
}
"EdwardS" wrote:
Mark,
Thanks for reply, I just realized that while cleaning code for you, I did
not clean everything (<eWCamera_Canon::CanonWrapper^is actually
<MyNamespace::Wrapper^>, I think that created a lot of confusion. Could
you
take a look at this code again, I greatly appreciate your help. Does it
change your response in anyway? In the following code Wrapper must be a
managed class, that is the whole point of my question - how to pass
managed
object (pass itself) into unmanaged area and later be casted into the
managed
type of itself, so that member methods of that managed class could be
used
inside that unmanaged static callback function?

namespace MyNamespace
{
public ref class Wrapper
{
unsigned long m_hSource;
public:
Wrapper();
bool SetupCallback();
};
}

Here is code inside Wrapper.cpp

unsigned long __stdcall CallBackFunc(const void * pData, unsigned
Context )
{
gcroot<MyNamespace::Wrapper^cwThis;

// Here is the place in question for casting back into managed class

// use m_hSource to delegate to C# User Interface
}

bool MyNamespace::Wrapper::SetupCallback()
{
unsigned int err;

// Registering callback with 3rd party DLL
err = RegisterCallback(CallBackFunc, this);
}
Dec 19 '07 #7

P: n/a
Mark Salsbery [MVP] wrote:
That won't work either. The only way you can pass a pointer to a
managed object to unmanaged code is with a pin_ptr. The problem is, a
pin_ptr only exists until it goes out of scope, and I don't think that's
going to work for this unmanaged callback scenario, since a pin_ptr
would go out of scope at the end of SetupCallback().
If a managed object needs to be pinned for a longer amount of time, the
GCHandle class can be used:

GCHandle gch = GCHandle::Alloc(my_object, GCHandleType::Pinned);

In the end it has to be freed:
gch.Free();

This can give a longer pinning lifetime than pin_ptr. On the other hand,
I would advice against pinning a lot of objects for an extensive amount
of time.

References:
http://msdn2.microsoft.com/en-us/library/83y4ak54.aspx
http://msdn2.microsoft.com/en-us/library/83y4ak54.aspx

Tom
Dec 19 '07 #8

P: n/a
"Tamas Demjen" <td*****@yahoo.comwrote in message
news:%2***************@TK2MSFTNGP06.phx.gbl...
Mark Salsbery [MVP] wrote:
>That won't work either. The only way you can pass a pointer to a managed
object to unmanaged code is with a pin_ptr. The problem is, a pin_ptr
only exists until it goes out of scope, and I don't think that's going to
work for this unmanaged callback scenario, since a pin_ptr would go out
of scope at the end of SetupCallback().

If a managed object needs to be pinned for a longer amount of time, the
GCHandle class can be used:

Right. That's why I originally suggested to the OP to store it using
gcroot<(which uses GCHandle but is cleaner than the messy GCHandle stuff
IMO) :)

He was still looking for a way to pass a managed pointer to unmanaged code,
however :)

Cheers,
Mark

--
Mark Salsbery
Microsoft MVP - Visual C++

>
GCHandle gch = GCHandle::Alloc(my_object, GCHandleType::Pinned);

In the end it has to be freed:
gch.Free();

This can give a longer pinning lifetime than pin_ptr. On the other hand, I
would advice against pinning a lot of objects for an extensive amount of
time.

References:
http://msdn2.microsoft.com/en-us/library/83y4ak54.aspx
http://msdn2.microsoft.com/en-us/library/83y4ak54.aspx

Tom
Dec 19 '07 #9

P: n/a
In my previous example, the Alloc() call in
MyNameSpace::Wrapper::SetupCallback() should be changed to

gchThis = GCHandle::Alloc(this); // Note: gchThis.Free() should be
called as soon as the GCHandle isn't needed!!!

sorry :)

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++

Dec 20 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.