我正在编写一个使用旧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代码中调用的,因为当我打破时,它似乎不知道它在一个类中,如果我改变了签名,那么相同的三个值会被传递并且变成任何东西 . 参数是第一位的 .
但是,我真的需要访问 class 成员,以避免一个非常脏的kludge . 由于类本身是驱动3D世界中的模型的原因,因此有两个或更多这些意味着我会得到回调:“234,pitch,90”并且我无法知道数据属于哪个模型的变量 .
我可以重新编译DLL(因为它是一个OSG插件)另外一个指向该实例的指针,或一个id,或者其他东西,并在回调中返回它,但我真的想避免这种情况,如果可能的话 .
我已经阅读过关于thunking的内容,但它看起来和大多数其他想法都需要访问创建回调的代码 . 有任何想法吗?
1 回答
您需要将指针传递给方法,但
uvarupdate
是指向函数的指针,这些是不同的类型 . 指向方法的指针包含指向实例的this
的隐式指针,它不适合函数指针 . 你需要以另一种方式传递this
.如果不更改回调的签名,则必须以某种方式计算实例(
this
) . 如果可以从name
参数确定,那么很容易 . 另一种方法是为您拥有的每个实例创建一个蹦床 . 如果只有少数实例,则可以为每个实例编写单独的trampoline函数 . 动态创建trampolines(在运行时)是棘手且不可移植的:实际上,您需要将一些机器指令写入RAM,以便他们使用正确的this
参数调用您的方法 . 但那是__某些库所做的事情(例如Delphi中的VCL) .