Я пишу простую библиотеку, которая использует libusb
для подключения к своему пользовательскому оборудованию, которое отправляет сигналы на хост-устройство каждые 50 мс.Он предназначен для предоставления простого уровня абстракции, чтобы пользователи вообще не беспокоились о libusb
.Мне нужно передать указатель на нестатическую функцию-член класса на libusb_fill_bulk_transfer .Т.е. мне нужно иметь отдельный обратный вызов для каждого экземпляра MyDevice без раскрытия логики libusb моим пользователям.
Базовая конструкция:
init the lib
int mylib_init(){
libusb_init(&context);
}
найти все совместимые устройства
int mylib_get_valid_devices(vector devs){
//...
libusb_device **devs1;
int countAll = libusb_get_device_list(context, &devs1);
//... fill devs
}
int mylib_print_device_info(MyDevice* dev);
подключить столько устройств, сколько ему нравится
int mylib_init_device(MyDevice* dev){
libusb_open(dev->device, &dev->dev_handle);
// check for kernel driver & remove if needed
libusb_claim_interface(dev->dev_handle, 0);
//...
}
настроить обратные вызовы для входящих данных на все экземпляры подключенных устройств
int mylib_start_transmission_async(MyDevice* dev, MyLibCallbackIn user_cb, unsigned char* buffer_in, int bufferSize){
libusb_control_transfer(dev->dev_handle, p1, p2, p3, p4, p5, p6, p7);
// .. rest of libusb_control_transfer -s
//start device:
int actual;
unsigned char startSig = 0b00110111;
libusb_bulk_transfer(dev->dev_handle, (1 | LIBUSB_ENDPOINT_OUT), &tosend, 1, &actual, 100);
dev->user_callback = user_cb;
dev->buffer_in = buffer_in;
dev->bufferSize = bufferSize;
//setup transfer
dev->transfer_in = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(dev->transfer_in, dev->dev_handle, LIBUSB_ENDPOINT_IN, dev->buffer_in,dev->bufferSize, cb_in, NULL, 0);
libusb_submit_transfer(dev->transfer_in);
}
отключить по окончании
int mylib_disconnect_device(MyDevice* device);
выйти из библиотеки
int mylib_exit();
MyDevice определяется как:
typedef int (*MyLibdCallbackIn)(unsigned char* buffer, int length);
class MyDevice{
unsigned char* buffer_in;
unsigned char* buffer_out;
libusb_device* device = nullptr;
libusb_device_handle* dev_handle = nullptr;
struct libusb_transfer* transfer_in = nullptr;
struct libusb_transfer* transfer_out = nullptr;
//this obviously wouldn't work because libusb doesn't accept it as a param:
void LIBUSB_CALL cb_in(struct libusb_transfer* transfer);
MyLibCallbackIn user_callback;
void run();
//...
}
, а cb_in определяется как:
void LIBUSB_CALL MyDevice::cb_in(libusb_transfer* transfer){
int r = libusb_submit_transfer(this->transfer_in);
callback_in(transfer->buffer, transfered);
}
Я не могу передать MyDevice::cb_in
в libusb_fill_bulk_transfer
потому что типы указателей на функции несовместимы.В то же время я не хочу, чтобы мои пользователи писали функцию обратного вызова с libusb_transfer*
в качестве параметра (выставляя libusb
) для прямой передачи в libusb_fill_bulk_transfer
.
РЕДАКТИРОВАТЬ: я пыталсяс
void LIBUSB_CALL callback_wrapper(struct libusb_transfer* transfer){
MyDevice* dev = reinterpret_cast<MyDevice*>(transfer->user_data);
dev->cb_in(transfer);
}
но получите Sementation fault (Core dumped)
ошибка