to set a native callback to managed member function

M

mot133t

I will quickly try to write a code that shows my intention. I will pass
unnecessary code.

typedef void(FP*)(LONG _param1, LONG _param2, BYTE* _pData);
class CNative
{
public: FP m_CallBack;

private: void JobDone()
{
for(iter i = m_Jobs.begin();i!=m_Jobs.end();++i)
{
// WORKS TWICE THAN CRASH
if(m_CallBack!=NULL) (*m_CallBack)(i->param1,i->param2, NULL);
}
}
};

ref class Managed
{
private: delegate void Handler(LONG _param1, LONG _param2, BYTE*
_pData);

private: CNative* m_Unmanaged;
private: Handler^ m_Handler;

private: /*USELESS static*/ void /*USELESS __stdcall */ Celebrate
(LONG _param1, LONG _param2, BYTE* _pData) {
// Invoke a nice event
}

public: void DoIt() {
m_Handler = gcnew Handler(this,&Managed::Celebrate);
// USELESS: pin_ptr<Handler^> pin(&m_Handler);
m_Unmanaged->m_CallBack =
Marshall::GetFunctionPointerForDelegate(m_Handler).ToPointer();
m_Unmanaged->DoYourJob();
}
};

I do get the right values from (*m_CallBack) twice. But then I beleive
stack is corrupted during function call, and BOOM :)

Can someone please tell me that this can not be done? I even don't know
how does it work twice.
And if you can tell the reason why is really appreciated. You can try
to explain me why do I try to do this :)
 
M

mot133t

Hi, again it's me.

Here is another attemp that failed but in a much nicer way:) This time
my function pointer cast is a used trick, which should work.

Now, I do have an exception at least : Cannot pass a GCHandle across
AppDomains.

// NO CLR

class CBase;
typedef void(CBase::*FP)(LONG _param1, LONG _param2, BYTE* _pData);
class CBase
{
public:
FP JobDoneCallBack;
CBase(){}
~CBase(){}
}

class CNative: public CBase
{

private: void JobDone()
{
for(iter i = m_Jobs.begin();i!=m_Jobs.end();++i)
{
// THIS->* is required, and I dont know why, CBase::* does not
work either
if(CBase::m_JobDoneCallBack!=NULL)
(this->*m_JobDoneCallBack)(i->param1,i->param2, NULL);
}
}

};

// CLR

delegate void Handler(LONG _param1, LONG _param2, BYTE* _pData);

class CDerived: CBase
{
private:
CBase* m_pSource;
gcroot<Handler^> m_Event;
public:
CDerived(CBase* _pSource, Handler^ _event)
:m_pSource(_pSource),m_Event(_event)
{
m_pSource->JobDoneCallBack = static_cast<FP>(&CDerived::Raiser);
}
private:
void Raiser(LONG _param1, LONG _param2, BYTE* _pData)
{
// THIS IS WHERE THE EXCEPTION OCCURS
// Cannot pass a GCHandle across AppDomains.
m_Event->Invoke(_param1, _param2, _pData);
}

}

ref class Managed
{


private: CNative* m_Unmanaged;
private: CDerived* m_Raiser;

private: void Celebrate(LONG _param1, LONG _param2, BYTE* _pData) {
// Invoke a nice event
}

public: void DoIt() {
// REGISTERING FOR EVENT
m_Raiser = new CDerived(m_Unmanaged,
gcnew
Handler(this,&Managed::Celebrate));
m_Unmanaged->DoYourJob();
}

};


Thanks to everyone who has read the entire code:) As always, your
thoughts are really appreciated.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top