R
ryan.mitchley
Hi all
I have a class (cPort) that is designed to receive objects and,
depending on the type, call a handler (callback) in any descendant of a
cProcessBlock class. Callback functions take a shared_ptr<cBase> as a
parameter, and return void.
The code was working fine, although I have encountered problems (under
a Microsoft compiler, of course - VC 8.0) when I attempt to add
callbacks to a class with multiple inheritance. I hate multiple
inheritance in general, but this is necessary to interface with another
library. I think there is some issue regarding the size of member
function pointers in VC.
Anyway - I believe that this code can be converted to use
boost::function and/or boost::bind to iron out these issues. The
problem is that I am going more than slightly squint when I read the
boost docs.
I have attached a reduced set of my code below. I would be extremely
grateful if someone could point out how this code could be converted to
use the boost representations.
Thanks for any and all replies!
Ryan
typedef void (cProcessBlock::*PortCallbackFnPtr)(shared_ptr<cBase>);
// structure that associates a callback function pointer with the
required caller
class cPortCallback : public cBase
{
public:
cPortCallback() :
m_pPortCallbackFn(NULL), m_pCaller(m_pNULL) { }
cPortCallback(PortCallbackFnPtr pPortCallbackFn,
shared_ptr<cBase> pCaller) :
m_pPortCallbackFn(pPortCallbackFn), m_pCaller(pCaller) { }
PortCallbackFnPtr m_pPortCallbackFn;
shared_ptr<cBase> m_pCaller;
};
class cPort : public cProcessBlock
{
public:
/// Add a new callback
void AddCallback(PortCallbackFnPtr NewCallbackFnPtr, std::string
strClassName,
shared_ptr<cBase> pCaller);
protected:
/// Callback registry (map of callback handlers)
map<string, cPortCallback> m_CallbackRegistry;
};
void cPort::AddCallback(PortCallbackFnPtr NewCallbackFnPtr, std::string
strClassName,
shared_ptr<cBase> pCaller)
{
m_CallbackRegistry[strClassName] = cPortCallback(NewCallbackFnPtr,
pCaller);
}
bool cPort::Timeslice()
// (called repeatedly in thread) - continuously receive new objects and
process using callbacks
{
shared_ptr<cBase> pNewObject;
pNewObject = Receive();
// Call appropriate callback depending on the received object's
class name
if (pNewObject) {
PortCallbackFnPtr CallbackFn =
m_CallbackRegistry[pNewObject->ClassName()].m_pPortCallbackFn;
if (CallbackFn) // if appropriate callback handler is found
((*(shared_polymorphic_cast<cProcessBlock>(m_CallbackRegistry[pNewObject->ClassName()].m_pCaller))).*(CallbackFn))(pNewObject);
}
return true;
}
An example of adding a callback:
AddCallback(static_cast<PortCallbackFnPtr>(&cGraph::OnNewGraphData),
"cRealMatrix", this);
I have a class (cPort) that is designed to receive objects and,
depending on the type, call a handler (callback) in any descendant of a
cProcessBlock class. Callback functions take a shared_ptr<cBase> as a
parameter, and return void.
The code was working fine, although I have encountered problems (under
a Microsoft compiler, of course - VC 8.0) when I attempt to add
callbacks to a class with multiple inheritance. I hate multiple
inheritance in general, but this is necessary to interface with another
library. I think there is some issue regarding the size of member
function pointers in VC.
Anyway - I believe that this code can be converted to use
boost::function and/or boost::bind to iron out these issues. The
problem is that I am going more than slightly squint when I read the
boost docs.
I have attached a reduced set of my code below. I would be extremely
grateful if someone could point out how this code could be converted to
use the boost representations.
Thanks for any and all replies!
Ryan
typedef void (cProcessBlock::*PortCallbackFnPtr)(shared_ptr<cBase>);
// structure that associates a callback function pointer with the
required caller
class cPortCallback : public cBase
{
public:
cPortCallback() :
m_pPortCallbackFn(NULL), m_pCaller(m_pNULL) { }
cPortCallback(PortCallbackFnPtr pPortCallbackFn,
shared_ptr<cBase> pCaller) :
m_pPortCallbackFn(pPortCallbackFn), m_pCaller(pCaller) { }
PortCallbackFnPtr m_pPortCallbackFn;
shared_ptr<cBase> m_pCaller;
};
class cPort : public cProcessBlock
{
public:
/// Add a new callback
void AddCallback(PortCallbackFnPtr NewCallbackFnPtr, std::string
strClassName,
shared_ptr<cBase> pCaller);
protected:
/// Callback registry (map of callback handlers)
map<string, cPortCallback> m_CallbackRegistry;
};
void cPort::AddCallback(PortCallbackFnPtr NewCallbackFnPtr, std::string
strClassName,
shared_ptr<cBase> pCaller)
{
m_CallbackRegistry[strClassName] = cPortCallback(NewCallbackFnPtr,
pCaller);
}
bool cPort::Timeslice()
// (called repeatedly in thread) - continuously receive new objects and
process using callbacks
{
shared_ptr<cBase> pNewObject;
pNewObject = Receive();
// Call appropriate callback depending on the received object's
class name
if (pNewObject) {
PortCallbackFnPtr CallbackFn =
m_CallbackRegistry[pNewObject->ClassName()].m_pPortCallbackFn;
if (CallbackFn) // if appropriate callback handler is found
((*(shared_polymorphic_cast<cProcessBlock>(m_CallbackRegistry[pNewObject->ClassName()].m_pCaller))).*(CallbackFn))(pNewObject);
}
return true;
}
An example of adding a callback:
AddCallback(static_cast<PortCallbackFnPtr>(&cGraph::OnNewGraphData),
"cRealMatrix", this);