0

我正在为使用旧的 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 代码调用的,因为当我中断时,它似乎不知道它在一个类中,如果我更改签名,相同的三个值会被传递并硬塞到任何东西中参数是第一位的。

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

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

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

4

1 回答 1

0

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

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

于 2013-08-27T19:38:18.757 回答