想想你的基本GLUT程序.它们只是从main方法运行并包含回调,如`glutMouseFunc(MouseButton),其中MouseButton是方法的名称.
我所做的是将主文件封装到一个类中,这样MouseButton不再是一个静态函数,而是一个实例.但这样做会给我一个编译错误:
错误2错误C3867:'StartHand :: MouseButton':函数调用缺少参数列表; 使用'&StartHand :: MouseButton'创建指向成员c:\ users\angeleyes\documents\visual studio 2008\projects\capstone ver 4\starthand.cpp的指针388 IK Engine
由于类非常庞大,因此无法提供代码示例.
我尝试过使用this->MouseButton但是会出现同样的错误.不能为回调提供指向实例函数的指针吗?
小智 5
正如错误消息所示,您必须使用&StartHand::MouseButton语法来获取指向成员函数的指针(ptmf); 这只是作为语言的一部分.
当使用ptmf时,你正在调用的函数,在这种情况下为glutMouseFunc,也必须期望获得一个ptmf作为回调,否则使用你的非静态MouseButton将无法工作.相反,一种常见的技术是回调与用户提供的void*上下文一起工作,该上下文可以是实例指针 - 但执行回调的库必须明确允许此参数.确保匹配外部库所期望的ABI(下面的handle_mouse函数)也很重要.
由于供应过剩不会允许用户供应的场景,你必须使用另一种机制:你的对象有过剩的当前窗口关联.然而,它确实提供了获取"当前窗口"的方法,并且我已经使用它来void*将窗口关联起来.然后你只需要创建一个trampoline来进行类型转换并调用方法.
机械:
#include <map>
int glutGetWindow() { return 0; } // make this example compile and run ##E##
typedef std::pair<void*, void (*)(void*,int,int,int,int)> MouseCallback;
typedef std::map<int, MouseCallback> MouseCallbacks;
MouseCallbacks mouse_callbacks;
extern "C" void handle_mouse(int button, int state, int x, int y) {
MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow());
if (i != mouse_callbacks.end()) { // should always be true, but possibly not
// if deregistering and events arrive
i->second.second(i->second.first, button, state, x, y);
}
}
void set_mousefunc(
MouseCallback::first_type obj,
MouseCallback::second_type f
) {
assert(obj); // preconditions
assert(f);
mouse_callbacks[glutGetWindow()] = MouseCallback(obj, f);
//glutMouseFunc(handle_mouse); // uncomment in non-example ##E##
handle_mouse(0, 0, 0, 0); // pretend it's triggered immediately ##E##
}
void unset_mousefunc() {
MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow());
if (i != mouse_callbacks.end()) {
mouse_callbacks.erase(i);
//glutMouseFunc(0); // uncomment in non-example ##E##
}
}
Run Code Online (Sandbox Code Playgroud)
例:
#include <iostream>
struct Example {
void MouseButton(int button, int state, int x, int y) {
std::cout << "callback\n";
}
static void MouseButtonCallback(
void* self, int button, int state, int x, int y
) {
static_cast<Example*>(self)->MouseButton(button, state, x, y);
}
};
int main() {
Example obj;
set_mousefunc(&obj, &Example::MouseButtonCallback);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意,您不再直接调用glutMouseFunc ; 它作为[un] set_mousefunc的一部分进行管理.
以防万一不清楚:我已经重写了这个答案,所以它应该对你有用,这样就避免了C/C++链接问题的争论.它将按原样编译和运行(没有过剩),它应该只有很小的修改过剩:评论或取消注释标记的4行##E##.
| 归档时间: |
|
| 查看次数: |
5807 次 |
| 最近记录: |