在 C++ 中使用 int 作为 void 指针
Using int as void pointer in C++
有一个 C++ 片段必须使用一些旧的纯 C event_handler 函数。
event_handler 有这个共同的签名:
add_event_handler(event_cb callback, void* user_data)
注:event_cb
是函数指针,可能与本题无关
user_data
定义为让用户传递一些额外的信息给回调。
现在,我的问题真的很简单,(如何)我可以传递一个简单的数字作为 user_data?
add_event_handler(mycallback, 1); // compilation error
显然,因为 1
不是 void*,但是,我怎样才能从堆栈(而不是堆)传递一些简单的变量?
例如:下面的代码是否正确?
int param=1;
add_event_handler(mycallback, ¶m);
因为这是可行的,但如果我必须注册更多的处理程序,会看起来很丑陋:
int param1=1;
int param2=2;
...
add_event_handler(mycallback, ¶m1);
add_event_handler(mycallback, ¶m2);
我只想为一堆事件定义相同的回调并给它们一个整数或枚举值作为 user_data 来决定在 我的回调.
这里是 mycallback:
static void mycallback(void* user_data) {
// do an action based on user_data, ie: if 1 passed, print "one", if 2 print "two".
}
请注意:我已经尝试搜索这类内容,但是 void*
主题很大,而且 Google 没那么聪明地理解我的愿望。抱歉,如果这里还有另一个相同主题的问题,我也没有找到。在这种情况下,请 post 它,并将其标记为 duplicate.
有一种约定,您将此类处理程序映射到 C++ classes,如下所示:
user_data
指向一个class 的实例
- 回调是此 class
的 static
方法
- 回调将
user_data
转换回 class 指针并使用该指针调用真正的回调方法。
您的 int
值将成为此 class 的单个成员。优点是当你需要另一个值时,你可以在 class.
中添加另一个成员
如果(且仅当)user_data
指针未在其他地方使用,您可以使用强制转换来转换sizeof
小于(或等于)sizeof(void*)
的任何整数到 void*
类型。
但是,要完全合规,您不能一步完成转换,必须通过中间转换完成:
add_event_handler(mycallback, reinterpret_cast<void*>(static_cast<intptr_t>(1)));
为了能够使用它,您需要进行相反的转换:
static void mycallback(void* user_data) {
int value = static_cast<int>(reinterpret_cast<intptr_t>(user_data));
}
像这样的转换通常被认为是不好的,但在某些情况下(比如你所拥有的)它确实是传递纯整数值的唯一可能方式。
[注意在32位系统上32位指针,像long long
这样的64位整数类型不能这样传递]
正如您在问题中指出的那样,另一种解决方案是使用单独的变量(或可能动态分配的值)来传递实际指针。
有一个 C++ 片段必须使用一些旧的纯 C event_handler 函数。
event_handler 有这个共同的签名:
add_event_handler(event_cb callback, void* user_data)
注:event_cb
是函数指针,可能与本题无关
user_data
定义为让用户传递一些额外的信息给回调。
现在,我的问题真的很简单,(如何)我可以传递一个简单的数字作为 user_data?
add_event_handler(mycallback, 1); // compilation error
显然,因为 1
不是 void*,但是,我怎样才能从堆栈(而不是堆)传递一些简单的变量?
例如:下面的代码是否正确?
int param=1;
add_event_handler(mycallback, ¶m);
因为这是可行的,但如果我必须注册更多的处理程序,会看起来很丑陋:
int param1=1;
int param2=2;
...
add_event_handler(mycallback, ¶m1);
add_event_handler(mycallback, ¶m2);
我只想为一堆事件定义相同的回调并给它们一个整数或枚举值作为 user_data 来决定在 我的回调.
这里是 mycallback:
static void mycallback(void* user_data) {
// do an action based on user_data, ie: if 1 passed, print "one", if 2 print "two".
}
请注意:我已经尝试搜索这类内容,但是 void*
主题很大,而且 Google 没那么聪明地理解我的愿望。抱歉,如果这里还有另一个相同主题的问题,我也没有找到。在这种情况下,请 post 它,并将其标记为 duplicate.
有一种约定,您将此类处理程序映射到 C++ classes,如下所示:
user_data
指向一个class 的实例
- 回调是此 class 的
- 回调将
user_data
转换回 class 指针并使用该指针调用真正的回调方法。
static
方法
您的 int
值将成为此 class 的单个成员。优点是当你需要另一个值时,你可以在 class.
如果(且仅当)user_data
指针未在其他地方使用,您可以使用强制转换来转换sizeof
小于(或等于)sizeof(void*)
的任何整数到 void*
类型。
但是,要完全合规,您不能一步完成转换,必须通过中间转换完成:
add_event_handler(mycallback, reinterpret_cast<void*>(static_cast<intptr_t>(1)));
为了能够使用它,您需要进行相反的转换:
static void mycallback(void* user_data) {
int value = static_cast<int>(reinterpret_cast<intptr_t>(user_data));
}
像这样的转换通常被认为是不好的,但在某些情况下(比如你所拥有的)它确实是传递纯整数值的唯一可能方式。
[注意在32位系统上32位指针,像long long
这样的64位整数类型不能这样传递]
正如您在问题中指出的那样,另一种解决方案是使用单独的变量(或可能动态分配的值)来传递实际指针。