我正在编写一个使用旧3D模型文件格式的模拟(Carbon Graphics'GEO,如果您感兴趣的话),以及此模型格式的OpenSceneGraph插件更新其内部变量的方式是通过注册回调模型在更新其值时调用的方法。回调具有模拟时间,变量名称及其当前值。您将返回该变量的新值。
所以,在我的代码中,我按如下方式设置回调:
headerNode->setUserUpdate(&FlightDriver::updateGeoVariable);
类headerNode所属的具有以下变量:
double (* uvarupdate)(const double t, const double val, const std::string name);
每隔一段时间,它会调用我设置为uvarupdate
的{{1}}:
updateGeoVariable(const double time, const double val, const std::string name)
{
return flightData->getValue(name);
}
为模型内的每个变量,一次一个。我不能使方法或flightData
成员静态,因为它们需要在每个实例中都是唯一的。
我预感到这个回调可能是从C代码调用的,因为当我中断时,它似乎不知道它在一个类中,如果我改变了签名,那么相同的三个值就会被传递掉首先是任何参数。
但是,我真的需要访问班级成员,以避免真正的脏污。由于类本身是驱动3D世界中的模型的原因,因此有两个或更多这些意味着我会得到回调:“234,pitch,90”并且我无法知道数据属于哪个模型的变量。
我可以重新编译DLL(因为它是一个OSG插件)另外指向该实例的指针,或者id,或者什么,并在回调中返回它,但我真的想避免这种情况,如果可能的。
我已经阅读过关于thunking的内容,但它看起来像那样,大多数其他想法都需要访问创建回调的代码。有什么想法吗?
答案 0 :(得分:0)
您需要传递指向方法的指针,但uvarupdate
是指向函数的指针,这些是不同的类型。指向方法的指针包含指向实例的this
的隐式指针,它不适合函数指针。您需要以其他方式传递this
。
如果不更改回调的签名,则必须以某种方式计算实例(this
)。如果可以从name
参数确定,那么很容易。另一种方法是为您拥有的每个实例创建一个蹦床。如果只有少数实例,则可以为每个实例编写单独的trampoline函数。动态创建trampolines(在运行时)是棘手且不可移植的:实际上,您需要将一些机器指令写入RAM,以便他们使用正确的this
参数调用您的方法。但这也是可能的,这就是一些库所做的(例如Delphi中的VCL)。