通过3d方库库回调成员函数 [英] Callback of member functions through 3d party library

查看:106
本文介绍了通过3d方库库回调成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用粒子模拟库。通过以下库函数将交互添加到粒子中:

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



现在我想向AddInteraction传递一个成员函数。我已经明白,这是不可能做到没有改变库函数。更改
库是我想避免的,但如果更改很小,我可以邮寄图书馆的作者,并要求它实现。



我想写一个简单的例子来说明如何做。可能有以下不同的解决方案:




  • Lambda表达式。这些是完美的,但是图书馆使用CUDA和NVCC,它们不支持Lamda表达式。


  • Functors。我认为functors可以做这项工作。但是,我没有设法让他们按我想要的方式工作。例如,
    我不能得到一个工作的函数列表。此问题在 http://www.tutok.sk/fastgl/callback.html

    如果组件有很多回调关系,变得不可行以将其全部参数化。考虑一个按钮,它希望维护
    动态的被调用者列表,以便在点击事件时被通知。由于被调用者类型被内置到Button类类型中,所以这个列表必须是同类的或无类型的。'



    我不得不承认我不明白





    有没有其他选择?或者有办法获得上述解决方案之一吗?



    非常感谢!



    编辑:



    感谢您的建议。他们帮助,但我不明白他们如何给我的问题一个完整的解决方案。具体来说,我想让这个工作:

      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); //通常会为每个粒子调用
    }
    }

    class Cell {
    public:
    void UpdateParticle(xyz * p,xyz * v );
    Cell()
    {
    AddInteraction(this-> UpdateParticle); //不工作
    }
    };

    int main()
    {
    Cell cell1;
    细胞cell2;

    for(int i = 0; i <100; i ++)
    {
    Simulate();
    }

    return 1;
    }


    解决方案

    void *参数,允许客户端代码为其可能需要的任何其他信息的占位符。



    这样,客户端代码可以传递任何他们想要的,原始类型当调用回调时。注意,调用代码知道原始类型。



    这种类型的接口允许C代码工作,但是如果需要,很容易将它包装在C ++对象中。



    编辑回答操作评论

    下面我将介绍修改Cell类别。

      class Cell 
    {
    public:
    static void UpdateParticle (void * stuff,xyz * p,xyz * v)//这必须像其他人提到的那样是静态的,注意额外的void *参数
    {
    Cell * c =(Cell *)stuff;
    // do work
    }

    Cell()
    {
    AddInteraction(this,UpdateParticle); //注意这需要两个项目,这两个项目都必须保存以供将来由AddInteraction使用,并通过模拟使用
    }
    };


    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.

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

    这篇关于通过3d方库库回调成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆