【问题标题】:Callback method cannot access member variables or instance回调方法无法访问成员变量或实例
【发布时间】:2013-08-27 19:15:43
【问题描述】:

我正在编写一个使用旧 3D 模型文件格式(如果您有兴趣,Carbon Graphics 的 GEO)的模拟,并且这种模型格式的 OpenSceneGraph 插件更新其内部变量的方式是您注册一个回调模型在更新其值时调用的方法。回调具有模拟时间、变量名称及其当前值。您将返回该变量的新值。

所以,在我的代码中,我将回调设置如下:

headerNode->setUserUpdate(&FlightDriver::updateGeoVariable);

headerNode 所属的类有以下变量:

double (* uvarupdate)(const double t, const double val, const std::string name);

每个间隔,它都会调用我设置的uvarupdate

updateGeoVariable(const double time, const double val, const std::string name)
{
    return flightData->getValue(name);
}

对于模型中的每个变量,一次一个。我无法将方法或 flightData 成员设为静态,因为它们需要在每个实例中都是唯一的。

我有一种预感,这个回调可能是从 C 代码调用的,因为当我中断时,它似乎不知道它在一个类中,如果我更改签名,相同的三个值会被传递并且硬塞进任何参数是第一个。

但是,我真的需要访问班级的成员,以避免真正肮脏的混乱。由于类本身是驱动 3D 世界中模型的驱动因素,因此拥有 2 个或更多这些意味着我会收到如下回调:“234,pitch,90”,我无法知道数据属于哪个模型的变量。

我可能会重新编译 DLL(因为它是一个 OSG 插件)以另外获取指向该实例的指针、id 或其他内容,并在回调中返回它,但我真的很想避免这种情况,如果可能。

我读过关于 thunking 的文章,但它看起来像这样,而且大多数其他想法都需要访问创建回调的代码。有什么想法吗?

【问题讨论】:

    标签: c++ static callback static-members openscenegraph


    【解决方案1】:

    您需要传递一个指向方法的指针,但uvarupdate 是指向函数的指针,它们是不同的类型。指向方法的指针包含指向实例的this 的隐式指针,它不适合函数指针。您需要通过其他方式传递this

    如果你不改变回调的签名,你必须以某种方式计算一个实例(this)。如果可以从name参数中确定,那就简单了。另一种方法是为您拥有的每个实例创建一个蹦床。如果只有少数实例,您可以为每个实例编写单独的蹦床函数。动态创建蹦床(在运行时)是棘手且不可移植的:事实上,您需要将一些机器指令写入 RAM,以便它们使用正确的 this 参数调用您的方法。但这也是可能的,这就是一些库所做的(例如 Delphi 中的 VCL)。

    【讨论】:

    • 我从未听说过蹦床。我会阅读的。那仍然需要更改uvarupdate的签名吗?如果是这样,我想我最终会尝试使用我需要的附加功能自己重新编译插件。
    • 蹦床是调用 C++ 方法的普通(非成员)函数。在这种情况下,无需更改uvarupdate 的签名,您只需将指向蹦床的指针传递给setUserUpdate。但是您需要为每个类实例使用不同的蹦床,这就是区分实例的方式。
    猜你喜欢
    • 2021-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-04
    • 1970-01-01
    • 2021-08-19
    • 2021-11-26
    相关资源
    最近更新 更多