2016-07-19 24 views
1

リアルタイム組み込みシステムの場合、私は割り込みハンドラを提供しようとしています。非スタティックメソッドポインタ(もちろんオブジェクトのインスタンス)も呼び出されます、割り込みが発生したとき。 CではC++の割り込みサービスルーチン

、これを行うのは簡単だった、例えば:

私の知る限り
void (*func)(void*) = 0; // <- method to be called goes here 
void* instance;   // <- instance for this-call goes here 

void InterruptHandler() 
{ 
    func(instance); 
} 

、これは非静的メソッドを呼び出すときに、この-呼び出すC++は、暗黙のうちにありません満たしています。

しかし、C++コンパイラは、(私がそうする方法を発見していない、少なくとも)関数ポインタにメソッドポインタをキャストすることを拒否 - 確かに分かりやすいですが、私の場合は一種の逆効果。

CのようにC++ this-callを直接エミュレートする方法はありますか? 私は代理人を知っていますが、私のコンパイラはC++ 98、ブーストライブラリなどに限定されています。カスタム軽量実装、たとえばSergey Ryazanovの不可能な高速C++デリゲートは、できるだけ避けたい特定のオーバーヘッドを提供します。

+1

メソッドは常に、おそらくあなたをトリップされ、隠し 'this'パラメータを持っています。役に立つ情報やヒントはこちら:https://isocpp.org/wiki/faq/pointers-to-members – user4581301

答えて

1

メソッドには、呼び出されているオブジェクトへのアクセスを提供するための隠しフィールドthisが常に含まれています。リストされたパラメータと必要なパラメータとの間に1対1の対応関係を持つCまたはCのような呼び出し動作が必要な割り込みハンドラからクラスを呼び出すには、Cのような動作を行わなければなりません。つまり、隠されたパラメータを持たないフリー関数または静的メソッドを意味します。

これは、未定義の動作についての仮定を掘り下げずに関数ポインタにメソッドを割り当てることができないことを意味します。

しかし、静的メソッドやフリー関数を使用すると、オブジェクトを利用できるようにすることができれば、オブジェクトに対してメソッドを呼び出すことができます。

void *は、ユーザーにより供給制御情報へのポインタである

void (*func)(void*) 

を考えると、簡単な解決策は、フォームの静的メソッドまたは遊離関数である

void handlerCaller(void* userp) 
{ 
    ISRHandlerClass * handlerp = (ISRHandlerClass *) userp; 
    handlerp->isrhandler(); // tiny bit may be lost here to subclass look-up 
} 

そして

void isrhandler() 

は、どんなことをしても実装されていますISRHandlerClassまたはISRHandlerClassの子が行う必要があります。

あなたはかなりhandlerCallerまたはそれに非常に似ているので、避けられないオーバーヘッドです。残りの部分は、ISRインターフェイスの一般的な使用方法によって異なります。

シンプルな汎用のISRハンドラの基底クラス:

class ISRHandlerClass 
{ 
    public: 
     virtual ~ISRHandlerClass() 
     { 
     } 
     // pure virtual to be implemented by specialized handler 
     virtual void isrhandler() = 0; 
}; 

と同じように、単純な実装

class FooHandler: public ISRHandlerClass 
{ 
    public: 
     void isrhandler() //override tag if you've got 'em 
     { 
      // read Foo and store in buffer to be processed by lower priority task 
     } 
}; 

しかし、あなたはスピードの賛成で一般化を投棄したい場合は、サブクラスで気にしないでください。複数のハンドラ呼び出し元が必要な場合は、複数のハンドラ呼び出し元のスペースを犠牲にします。

void FooHandlerCaller(void* userp) 
{ 
    FooHandler * handlerp = (FooHandler *) userp; 
    handlerp->isrhandler(); 
} 

void BarHandlerCaller(void* userp) 
{ 
    BarHandler * handlerp = (BarHandler *) userp; 
    handlerp->isrhandler(); 
} 

それとも

template <class TYPE> 
void handlerCaller(void* userp) 
{ 
    TYPE * handlerp = (TYPE *) userp; 
    handlerp->isrhandler(); 
} 

使い方

class FooHandler 
{ 
    public: 
     void isrhandler() 
     { 
      // read Foo and store in buffer to be processed by lower priority task 
     } 
}; 

void (*func)(void*) = handlerCaller<FooHandler>; 
FooHandler handler; 
void* instance = (void *)&handler; 
関連する問題