Функция libusb callback_in как член класса в C++

У меня проблема с определением и использованием функции обратного вызова в libusb_fill_bulk_transfer при вызове в качестве члена класса в C++.

Вот определение в классе:

namespace usb_connector
{
    class USBConnector
    {
    public:
        USBConnector();
        ~USBConnector();
        int connect(void);
        void read(void);
        void write(unsigned char *);
        void disconnect(void);
        void LIBUSB_CALL callback_in(struct libusb_transfer*);
...

Вот реализация в классе:

void LIBUSB_CALL usb_connector::USBConnector::callback_in(struct libusb_transfer *transfer)
{
    if (transfer == NULL) {
        cout << "No libusb_transfer..." << endl;
    }
    else {
        cout << "libusb_transfer structure: " << endl;
        cout << "actual_length = " << transfer->actual_length << endl;
        for (int i = 0; i < transfer->actual_length; i++) {
            cout << transfer->buffer[i];
        }
        cout << endl;
    }

    return;
}

И вот как я это называю:

...
...
libusb_fill_bulk_transfer( transfer_in, usb_dev, USB_ENDPOINT_IN,
            in_buffer,  LEN_IN_BUFFER, callback_in, NULL, 0);
...
...

Ошибка, которую я получаю, следующая:

ошибка: невозможно преобразовать 'usb_connector::USBConnector::callback_in' из типа 'void (usb_connector::USBConnector::)(libusb_transfer*)' в тип 'libusb_transfer_cb_fn {aka void ()(libusb_transfer)} ' in_buffer, LEN_IN_BUFFER, callback_in, NULL, 0);

Как я могу использовать функцию обратного вызова в качестве члена класса и как мне ее вызвать?


person tik    schedule 07.04.2016    source источник


Ответы (1)


Указатель на функцию-член класса и указатель на функцию несовместимы в C++.

Согласно документации, прототипом обратного вызова является:

typedef void( * libusb_transfer_cb_fn) (struct libusb_transfer *transfer)

И struct libusb_transfer имеет поле user_data, которое, очевидно, заполняется во время установки обратного вызова, поэтому вам нужна оболочка:

void LIBUSB_CALL callback_wrapper(struct libusb_transfer *transfer)
{
    usb_connector::USBConnector *connector = reinterpret_cast<usb_connector::USBConnector*>(transfer->user_data);
    connector->callback_in(transfer);
}

И передать this во время звонка:

...
...
libusb_fill_bulk_transfer( transfer_in, usb_dev, USB_ENDPOINT_IN,
            in_buffer,  LEN_IN_BUFFER, callback_wrapper, this, 0);
person user2807083    schedule 07.04.2016
comment
Строго говоря, callback_wrapper() должно быть extern "C". - person Michael Burr; 07.04.2016
comment
@MichaelBurr, я так не думаю, extern "C" просто отключите изменение и имеет смысл, если вы свяжете эту функцию с простым объектным файлом c, который вызывает вашу функцию C++ по имени. Но мы просто хотим вызывать функцию по указателю, и здесь нечего делать с искажениями. - person user2807083; 07.04.2016