I’m working with a particle simulation library. The way interactions are added to particles it through the following library function:
AddInteraction(ParticleSet particleSet, void(*interaction)(xyz* p, xyz* v))
I now want to pass a member function to AddInteraction. I’ve understood that this is impossible to do without changing the library function. Changing
the library is something I’d like to avoid, but if the change is small I can mail the author of the library and ask for it to be implemented.
I want to write a simple example of how it can be done. Different solutions are possible:
-
Lambda expressions. These would be perfect, however the library uses CUDA and NVCC, which don’t support Lamda expressions yet.
-
Functors. I thought functors could do the job. However, I haven’t managed to get them working in the way I want. For example,
I can’t get a list of functors to work. This problem is described in http://www.tutok.sk/fastgl/callback.html under Parameterize the Caller:
‘ If a component has many callback relationships it quickly becomes unworkable to parameterize them all. Consider a Button that wants to maintain a
dynamic list of callees to be notified upon a click event. Since the callee type is built into the Button class type, this list must be either homogeneous or typeless.’
I have to admit that I don’t understand everything that is written on that site, so there might be an answer there.
- Using a 3d party library. For example the ‘Callbacks Using Template Functors Library’ as described on http://www.tutok.sk/fastgl/callback.html, or using Boost::Function. However, these will probably require major changes to the particle library I’m working with, right?
Are there any alternatives? Or is there a way to get one of the above solutions to work?
Thanks a lot!
Edit:
Thanks for your suggestions. They help, but I fail to see how they give a complete solution to my problem. Specifically, I’m trying to get this to work:
std::vector<void(*)(xyz*,xyz*)> interactionList;
void AddInteraction(void(*func)(xyz*,xyz*))
{
interactionList.push_back(func);
}
void Simulate()
{
for(size_t i = 0; i < interactionList.size(); i++)
{
interactionList[i](0,0); //Would normally be called for every particle
}
}
class Cell {
public:
void UpdateParticle(xyz* p, xyz* v);
Cell()
{
AddInteraction(this->UpdateParticle); //Does not work
}
};
int main()
{
Cell cell1;
Cell cell2;
for(int i = 0; i < 100; i++)
{
Simulate();
}
return 1;
}
Typically, callback function have a void * argument that allows client code a placeholder for any other information it may require.
This way, the client code can pass in anything they want and recast it back to the original type when the callback is invoked. Note, the calling code knows the original type.
This type of interface allows C only code to work but it’s pretty easy to wrap this in a C++ object if needed. At the very least, the library author should provide this.
EDIT TO ANSWER OPs COMMENT
Below I’ve modified the Cell class appropriately.