0

我正在使用粒子模拟库。通过以下库函数将交互添加到粒子的方式:

AddInteraction(ParticleSet particleSet, void(*interaction)(xyz* p, xyz* v))

我现在想将成员函数传递给 AddInteraction。我已经明白,如果不更改库函数,这是不可能做到的。我想避免更改库,但如果更改很小,我可以邮寄库的作者并要求实施。

我想写一个简单的例子来说明它是如何完成的。不同的解决方案是可能的:

  • Lambda 表达式。这些将是完美的,但是该库使用 CUDA 和 NVCC,它们还不支持 Lamda 表达式。

  • 函子。我认为函子可以完成这项工作。但是,我还没有设法让他们按照我想要的方式工作。例如,我无法获得工作的函子列表。这个问题在http://www.tutok.sk/fastgl/callback.html中的Parameterize the Caller中有所描述:

' 如果一个组件有很多回调关系,那么将它们全部参数化很快就会变得不可行。考虑一个 Button,它想要维护一个动态的被调用者列表,以便在点击事件时得到通知。由于被调用者类型内置于 Button 类类型中,因此该列表必须是同质的或无类型的。

我不得不承认我不理解该网站上写的所有内容,因此那里可能会有答案。

  • 使用 3d 派对库。例如http://www.tutok.sk/fastgl/callback.html上描述的“使用模板函子库的回调” ,或使用 Boost::Function。但是,这些可能需要对我正在使用的粒子库进行重大更改,对吧?

有没有其他选择?或者有没有办法让上述解决方案之一起作用?

非常感谢!

编辑:

感谢您的建议。他们有帮助,但我看不到他们如何为我的问题提供完整的解决方案。具体来说,我正试图让它发挥作用:

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;
}
4

3 回答 3

7
于 2012-07-16T15:45:39.577 回答
1

您描述的内容是不可能的,因为库不知道它必须将this参数传递给您的成员函数。如果interaction接受为用户保留的参数,您可以这样做。如果您在任何给定时间调用单个对象实例AddInteraction,则可以存储指向该实例的指针:

Object *Object::only_instance;

void Object::AddInteractionCaller() {
   only_instance = this;
   AddInteraction(set, interaction_fn); 
}

void interaction_fn(xyz* p, xyz* v) {
  only_instance->interaction(p, v);
}
于 2012-07-16T15:28:56.810 回答
0

通常,回调函数有一个 void * 参数,它允许客户端代码作为它可能需要的任何其他信息的占位符。

这样,客户端代码可以传入他们想要的任何内容,并在调用回调时将其重新转换回原始类型。请注意,调用代码知道原始类型。

这种类型的接口只允许 C 代码工作,但如果需要,可以很容易地将其包装在 C++ 对象中。至少,图书馆作者应该提供这个。

编辑回答 OPs 评论
下面我已经适当地修改了 Cell 类。

class Cell  
{ 
public:
  static void UpdateParticle(void *stuff, xyz* p, xyz* v)  // this has to be static as others have mentioned, note the additional void * argument
  {
      Cell * c = (Cell *) stuff;
      // do work
  }  

  Cell()
  {
      AddInteraction(this, UpdateParticle); // note this takes a two items, both of which have to be saved for future use by AddInteraction and utilized by Simulate
  }
};  
于 2012-07-16T15:40:49.310 回答