【发布时间】:2015-01-08 08:16:42
【问题描述】:
这个问题来自here。但是,上一个问题的措辞非常糟糕(实际上是错误的),建议我从头开始再问一次。
我有一个 C 函数指针表。
一些 C 代码(我们称之为 lib-X)有一个基本的构建块(我们称之为 X 对象)。每个 X 对象都可以调用此表上的函数。
这些表函数通常具有不同的签名(请参阅 typedefs here),尽管多个函数可以共享相同的签名。表中大约有 100 个这样的函数。
在 C++ 中,每个 X 对象都有一个关联的 Final:Base 类。
我想将这些调用转发到 X 对象的相应 C++ Final 实例,但我想将其包含在 try/catch 中,因为 C++ 使用者可能会提供一个有缺陷的 Final。
所以我有一个 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
}
}
(来源here)
我正在尝试提出一种紧凑的设计,以允许这种异常安全的蹦床。
我目前的进度是[已删除,请参阅下面的答案]
【问题讨论】:
-
您没有在底部链接的代码示例中调用
trampoline.enable_f2();(“EDIT”)。 -
@dyp,啊!谢谢! (错误代码现已删除)
-
可能是错的,但是NVI(非虚拟接口)习语不能解决这个问题吗?基类具有转发给受保护助手的公共非虚拟方法。然后,非虚拟方法可以非常方便地查看您的 try/catch 代码。
标签: c++ c++11 trampolines