Modern C++17 RAII wrapper library for libusb-1.0.
- RAII everywhere — no manual resource cleanup, ever
- No raw libusb types in the public API — safe, opaque C++ interfaces
- Exception-based error handling with full error context
- Move semantics and value types throughout
- CMake build with
find_package()andpkg-configsupport
#include <usbcxx/usbcxx.hpp>
#include <cstdio>
int main() {
usbcxx::Context ctx;
for (const auto& dev : ctx.get_device_list()) {
auto desc = dev.get_descriptor();
std::printf("ID %04x:%04x\n", desc.vendor_id, desc.product_id);
}
}- C++17 compiler (GCC 8+, Clang 7+)
- CMake 3.16+
- libusb-1.0 development headers
# Debian/Ubuntu
sudo apt install libusb-1.0-0-dev pkg-config cmake
# Fedora
sudo dnf install libusb1-devel pkgconfig cmake
# Arch
sudo pacman -S libusb cmake pkgconfBy default, both static (libusbcxx.a) and shared (libusbcxx.so) libraries are built:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallelcmake -B build -DCMAKE_BUILD_TYPE=Release -DUSBCXX_BUILD_SHARED=OFF
cmake --build build --parallel
# produces: build/libusbcxx.acmake -B build -DCMAKE_BUILD_TYPE=Release -DUSBCXX_BUILD_STATIC=OFF
cmake --build build --parallel
# produces: build/libusbcxx.so -> libusbcxx.so.0 -> libusbcxx.so.0.1.0cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
# produces: build/libusbcxx.a + build/libusbcxx.so| Option | Default | Description |
|---|---|---|
USBCXX_BUILD_STATIC |
ON |
Build static library (libusbcxx.a) |
USBCXX_BUILD_SHARED |
ON |
Build shared library (libusbcxx.so) |
USBCXX_BUILD_TESTS |
ON |
Build unit tests (requires internet for GoogleTest) |
USBCXX_BUILD_EXAMPLES |
OFF |
Build example programs |
ctest --test-dir build --output-on-failurecmake -B build -DUSBCXX_BUILD_EXAMPLES=ON
cmake --build build --parallel
./build/examples/list_devicescmake -B build -DCMAKE_BUILD_TYPE=Release -DUSBCXX_BUILD_TESTS=OFF
cmake --build build --parallel
sudo cmake --install buildThis installs both static and shared libraries (unless disabled), headers, CMake config files, and a pkg-config .pc file.
find_package(usbcxx REQUIRED)
# Uses usbcxx::usbcxx (prefers static if both installed)
target_link_libraries(myapp PRIVATE usbcxx::usbcxx)
# Or link explicitly against a specific variant:
target_link_libraries(myapp PRIVATE usbcxx::usbcxx_static) # static
target_link_libraries(myapp PRIVATE usbcxx::usbcxx_shared) # sharedg++ -std=c++17 myapp.cpp $(pkg-config --cflags --libs usbcxx)| Class | Description |
|---|---|
usbcxx::Context |
Manages a libusb session. Entry point for device enumeration. |
usbcxx::Device |
Represents a USB device. Copyable (ref-counted). |
usbcxx::DeviceHandle |
An opened device. Provides synchronous transfers. Move-only. |
usbcxx::InterfaceClaim |
RAII guard for a claimed USB interface. |
usbcxx::Transfer |
Asynchronous transfer with callback support. |
usbcxx::UsbException |
Exception type wrapping libusb error codes. |
| Type | Description |
|---|---|
DeviceDescriptor |
USB device descriptor fields |
ConfigDescriptor |
Configuration descriptor with interfaces and endpoints |
InterfaceDescriptor |
Interface descriptor with endpoints |
EndpointDescriptor |
Endpoint descriptor fields |
TransferResult |
Async transfer result passed to callbacks |
| Enum | Description |
|---|---|
Error |
libusb error codes |
TransferStatus |
Async transfer completion status |
TransferType |
Control, Bulk, Interrupt, Isochronous |
Direction |
In / Out |
LogLevel |
Debug verbosity |
#include <usbcxx/usbcxx.hpp>
usbcxx::Context ctx;
auto devices = ctx.get_device_list();
for (const auto& dev : devices) {
auto desc = dev.get_descriptor();
if (desc.vendor_id == 0x1234 && desc.product_id == 0x5678) {
auto handle = dev.open();
auto claim = handle.claim_interface(0);
std::vector<uint8_t> buf(64);
int n = handle.bulk_transfer(0x81, buf, 1000);
// buf[0..n-1] contains received data
}
}MIT — see LICENSE.