error: invalid use of non-static member function ‘int test::hotplug_callback(libusb_context*, libusb_device*, libusb_hotplug_event, void*)’
error: invalid use of non-static member function ‘int test::hotplug_callback(libusb_context*, libusb_device*, libusb_hotplug_event, void*)’
我改编了来自
的 libusb 热插拔示例
* libusb example program for hotplug API
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
(下面的代码)作为测试并将其放在 class 中,因为我的真实程序也有同样的问题。
我知道如果我将 static 放在它起作用的两个回调前面,但我不希望它们是静态的。我想从回调中访问我的实例变量。这个想法是用户插入一个 usb 设备,我们称它为 usbXYZ。从回调中,我实例化 class usbXYZ 并放入 std::map - 用户将其删除,我将其从地图中删除。包含 std::map 及其中对象的 class 具有写入设备的 'higher level' 方法。
请问如何使回调函数工作 none 静态?如果可能的话,请解释一下,因为我不明白。谢谢
#include <stdlib.h>
#include <stdio.h>
#include <thread>
#include "libusb-1.0/libusb.h"
class test{
public:
test() {
okGo();
}
private:
int done = 0;
libusb_device_handle *handle = NULL;
int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
struct libusb_device_descriptor desc;
int rc;
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
rc = libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error getting device descriptor\n");
}
printf ("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct);
if (handle) {
libusb_close (handle);
handle = NULL;
}
rc = libusb_open (dev, &handle);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error opening device\n");
}
done++;
return 0;
}
int LIBUSB_CALL hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
printf ("Device detached\n");
if (handle) {
libusb_close (handle);
handle = NULL;
}
done++;
return 0;
}
int okGo(){
libusb_hotplug_callback_handle hp[2];
int product_id, vendor_id, class_id;
int rc;
vendor_id = LIBUSB_HOTPLUG_MATCH_ANY;
product_id = LIBUSB_HOTPLUG_MATCH_ANY;
class_id = LIBUSB_HOTPLUG_MATCH_ANY;
rc = libusb_init (NULL);
if (rc < 0)
{
printf("failed to initialise libusb: %s\n", libusb_error_name(rc));
return EXIT_FAILURE;
}
if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
printf ("Hotplug capabilites are not supported on this platform\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_ENUMERATE, vendor_id,
product_id, class_id, hotplug_callback, NULL, &hp[0]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 0\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, vendor_id,
product_id,class_id, hotplug_callback_detach, NULL, &hp[1]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 1\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
while (done < 20) {
//rc = libusb_handle_events (NULL);
if (libusb_handle_events_completed(nullptr, nullptr) != LIBUSB_SUCCESS)
printf("libusb_handle_events() failed: %s\n", libusb_error_name(rc));
}
if (handle) {
libusb_close (handle);
}
libusb_exit (NULL);
return EXIT_SUCCESS;
}
};
int main(int argc, char *argv[])
{
std::unique_ptr<test> testClass1 = std::make_unique<test>();
//just test
for (;;)
{
//main service loop
std::this_thread::sleep_for(std::chrono::microseconds(2000000));
}
}
libusb是一个C库,它只能接受非成员函数指针。非成员函数(或 static
成员函数)指针与指向非静态成员函数的指针之间的区别在于,非静态成员函数需要一个 object 被调用,C 不了解 C++ "objects".
使用 libusb 你可以解决它,使用 static
成员函数和用户数据指针(你现在传递一个空指针)。
例如
class test
{
// ...
static int LIBUSB_CALL static_hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
return reinterpret_cast<test*>(user_data)->hotplug_callback_detach(ctx, dev, event);
}
int hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event)
{
// Current code
}
// ...
int okGo()
{
// ...
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, vendor_id,
product_id,class_id, static_hotplug_callback_detach, this, &hp[1]);
// ...
}
注意注册回调时使用了static
成员函数,this
作为用户数据指针传递。
我改编了来自
的 libusb 热插拔示例* libusb example program for hotplug API
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
(下面的代码)作为测试并将其放在 class 中,因为我的真实程序也有同样的问题。 我知道如果我将 static 放在它起作用的两个回调前面,但我不希望它们是静态的。我想从回调中访问我的实例变量。这个想法是用户插入一个 usb 设备,我们称它为 usbXYZ。从回调中,我实例化 class usbXYZ 并放入 std::map - 用户将其删除,我将其从地图中删除。包含 std::map 及其中对象的 class 具有写入设备的 'higher level' 方法。
请问如何使回调函数工作 none 静态?如果可能的话,请解释一下,因为我不明白。谢谢
#include <stdlib.h>
#include <stdio.h>
#include <thread>
#include "libusb-1.0/libusb.h"
class test{
public:
test() {
okGo();
}
private:
int done = 0;
libusb_device_handle *handle = NULL;
int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
struct libusb_device_descriptor desc;
int rc;
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
rc = libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error getting device descriptor\n");
}
printf ("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct);
if (handle) {
libusb_close (handle);
handle = NULL;
}
rc = libusb_open (dev, &handle);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error opening device\n");
}
done++;
return 0;
}
int LIBUSB_CALL hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
printf ("Device detached\n");
if (handle) {
libusb_close (handle);
handle = NULL;
}
done++;
return 0;
}
int okGo(){
libusb_hotplug_callback_handle hp[2];
int product_id, vendor_id, class_id;
int rc;
vendor_id = LIBUSB_HOTPLUG_MATCH_ANY;
product_id = LIBUSB_HOTPLUG_MATCH_ANY;
class_id = LIBUSB_HOTPLUG_MATCH_ANY;
rc = libusb_init (NULL);
if (rc < 0)
{
printf("failed to initialise libusb: %s\n", libusb_error_name(rc));
return EXIT_FAILURE;
}
if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
printf ("Hotplug capabilites are not supported on this platform\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_ENUMERATE, vendor_id,
product_id, class_id, hotplug_callback, NULL, &hp[0]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 0\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, vendor_id,
product_id,class_id, hotplug_callback_detach, NULL, &hp[1]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 1\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
while (done < 20) {
//rc = libusb_handle_events (NULL);
if (libusb_handle_events_completed(nullptr, nullptr) != LIBUSB_SUCCESS)
printf("libusb_handle_events() failed: %s\n", libusb_error_name(rc));
}
if (handle) {
libusb_close (handle);
}
libusb_exit (NULL);
return EXIT_SUCCESS;
}
};
int main(int argc, char *argv[])
{
std::unique_ptr<test> testClass1 = std::make_unique<test>();
//just test
for (;;)
{
//main service loop
std::this_thread::sleep_for(std::chrono::microseconds(2000000));
}
}
libusb是一个C库,它只能接受非成员函数指针。非成员函数(或 static
成员函数)指针与指向非静态成员函数的指针之间的区别在于,非静态成员函数需要一个 object 被调用,C 不了解 C++ "objects".
使用 libusb 你可以解决它,使用 static
成员函数和用户数据指针(你现在传递一个空指针)。
例如
class test
{
// ...
static int LIBUSB_CALL static_hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
return reinterpret_cast<test*>(user_data)->hotplug_callback_detach(ctx, dev, event);
}
int hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event)
{
// Current code
}
// ...
int okGo()
{
// ...
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, vendor_id,
product_id,class_id, static_hotplug_callback_detach, this, &hp[1]);
// ...
}
注意注册回调时使用了static
成员函数,this
作为用户数据指针传递。