0

粒子シミュレーション ライブラリを使用しています。次のライブラリ関数を使用して相互作用を粒子に追加する方法:

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

AddInteraction にメンバー関数を渡したいと思います。ライブラリ関数を変更しない限り、これは不可能であることがわかりました。ライブラリの変更は避けたいところですが、変更が小さい場合は、ライブラリの作成者にメールして実装を依頼することもできます。

それがどのように行われるかの簡単な例を書きたいと思います。さまざまな解決策が可能です:

  • ラムダ式。これらは完璧ですが、ライブラリはラムダ式をまだサポートしていない CUDA と NVCC を使用しています。

  • ファンクタ。私はファンクターが仕事をすることができると思った。しかし、私はそれらを思い通りに機能させることができませんでした。たとえば、機能するファンクターのリストを取得できません。この問題はhttp://www.tutok.sk/fastgl/callback.htmlParameterize the Callerで説明されています。

' コンポーネントに多くのコールバック関係がある場合、それらすべてをパラメーター化するのはすぐに不可能になります。クリックイベントで通知される呼び出し先の動的リストを維持したいボタンを考えてみましょう。呼び出し先の型は Button クラスの型に組み込まれているため、このリストは同種または型なしでなければなりません。

私はそのサイトに書かれているすべてを理解しているわけではないことを認めなければならないので、そこに答えがあるかもしれません.

  • サードパーティ ライブラリの使用。たとえば、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++オブジェクトでラップするのは非常に簡単です。少なくとも、図書館の作者はこれを提供する必要があります。

OPコメント
に答える ために編集以下では、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 に答える