この質問はここから続きます。しかし、前の質問の言い回しが非常に悪かったため (実際には間違っていました)、最初からもう一度質問するよう提案されました。
C 関数ポインターのテーブルがあります。
一部の C コード (lib-X と呼びましょう) には、基本的な構成要素 (X オブジェクトと呼びましょう) があります。各 X オブジェクトは、このテーブルの関数を呼び出すことができます。
これらのテーブル関数は、通常、異なるシグネチャを持ちます (ここの typedef を参照)。ただし、複数の関数が同じシグネチャを共有することは可能です。表には、これらの関数が約 100 あります。
C++ では、各 X オブジェクトに関連付けられた Final:Base クラスがあります。
そして、これらの呼び出しを X オブジェクトの対応する C++ Final インスタンスに転送したいのですが、C++ コンシューマーがバグのある Final を提供する可能性があるため、これを try/catch 内に囲みたいと思います。
したがって、テーブルの各エントリに対して仮想関数を持つ C++ 基本クラスがあります。
次に、基本クラスから派生した C++ Final クラス (多くの場合、Final1 Final2 Final3 など) があります。
だから今、私はハンドラーを書く必要があります
最初の「self」パラメーターを取得します (これは常に、関数を呼び出した X オブジェクトへのポインターになります)
関連する C++ 基本クラス インスタンスを取得します。
try catch ブロック内で、対応する仮想関数を呼び出し、残りのすべてのパラメーターを転送します。
...実際に Final でオーバーライドを呼び出します。
これは、インセプションのプロットを理解しようとするようなものです。lib-X は実際には Python ランタイムですが、私は物事を一般的なものにしようとしています。
問題は、これらの関数が数十あることです。これにより、非常に面倒で保守不可能な C++ コードが作成されます。それぞれのトランポリン関数を手動で作成する必要がある場合は、次のようになります。
extern "C" PyObject *call_handler( PyObject *self, PyObject *args, PyObject *kw )
{
try
{
PythonExtensionBase *p = getPythonExtensionBase( self );
if( kw != NULL )
return new_reference_to( p->call( Object(args), :Object(kw) ) );
else
return new_reference_to( p->call( Object(args), Object() ) );
}
catch( Py::Exception & )
{
return NULL; // indicate error
}
}
(ソースはこちら)
私は、この例外的に安全なトランポリンを可能にするコンパクトなデザインを考え出そうとしています.
現在の進捗状況は [削除済み、下記の回答を参照]