libusb
libusb copied to clipboard
C++ symbol for libusb_set_option not exported correctly
The libusb_set_option() function is not being properly exported for use with C++ in MSVC.
I believe the export was briefly specified correctly in @dickens original commit, here: https://github.com/libusb/libusb/blob/v1.0.22-rc1/libusb/libusb-1.0.def#L156
It looks like it's changed several times since then, but the export style of this function does not match other exports in the master branch.
Please help to create a pull request if you can. Thanks.
@tckillian @tormodvolden Please check if #949 is correct or not. Thanks.
First time learning to create a pull request. :-)
From going through the git log, it was only changed once, in commit 0aac390, maybe inadvertently, @dickens?
BTW shouldn't the ordinal numbers be unique for each function? https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-def-files?view=msvc-160
It looks like people regenerate this file from a DLL instead of maintaining it by hand.
Note the original commit was commit 539f22e2, not in the RC that you both are referring to. It was actually modified twice:
- commit 46874013 removed the "@8" ordinal number.
- commit 0aac390 added the underscore
@hjelmn what do you think about the ordinal numbers?
@tormodvolden It seems to me the ordinal number is not unique. I believe it is there to support legacy code (32bit only). But now we need to see if 8 is correct or not based on the following.
Ref: https://docs.microsoft.com/en-us/cpp/build/reference/exports?view=msvc-160
Because the MSVC compiler uses name decoration for C++ functions, you must either use the decorated name internal_name or define the exported functions by using extern "C" in the source code. The compiler also decorates C functions that use the __stdcall calling convention with an underscore (_) prefix and a suffix composed of the at sign (@) followed by the number of bytes (in decimal) in the argument list.
@tormodvolden From libusb-1.0.def history file, it seems that this should be manually generated. https://github.com/libusb/libusb/commit/b88ce7d2450a2d77b84cca5ffe6bcb449a5ae05b
* Generated from a MinGW32 generated DLL using the command:
echo -e "LIBRARY\nEXPORTS" > libusb-1.0.def; strings libusb-1.0.dll | grep libusb | grep @ | sort | sed -e "s/\(.*\)@\([0-9]*\)/ \1\n \1@\2 = \1/" >> libusb-1.0.def
I also found the reference from Pete's post to the mailing list.
On Tue, May 10, 2011 at 5:50 AM Pete Batard wrote:
Just putting a note there for manual .def generation. If you have a MinGW32 generated DLL, the following should generate the expected .def:
$ echo -e "LIBRARY\nEXPORTS" > libusb-1.0.def; strings libusb-1.0.dll | grep libusb | grep @ | sort | sed -e "s/\(.*\)@\([0-9]*\)/ \1\n \1@\2 = \1/" >> libusb-1.0.def
Regards,
/Pete
Chris is also generating the def file from the DLL.
https://github.com/libusb/libusb/commit/cec3514dd4c6a56b543559874f2b40f3e0c67fe2
Windows: Regenerate libusb-1.0.def file from latest DLL
But many times it will be manually created.
The usage of the def file is to make the DLL interchangeable between MinGW and MSVC. There was a long discussion here.
https://marc.info/?l=libusb-devel&m=128076361626828&w=4 List: libusb-devel Subject: Re: [Libusb-devel] interchangeability of MinGW and MS DLLs From: Pete Batard Date: 2010-08-02 15:39:52
All things considered, I think the solution I'd prefer would be to ditch __declspec(dllexport) altogether and revert to using a def file (while leaving WINAPI as the default calling convention).
The problem of keeping the .def in sync with what we have in our source could be solved with a sed script, called at the end of autogen.sh, that would update the .def by picking up all API_EXPORTED calls we have in core (and of course, as current .def would be provided as well).
This would keep libusb.h free from the redundant LIBUSB_EXP, as Daniel wanted, keep the use of WINAPI, and might ease up the life of developers, as having a .def allows for easy creation of the DLL library wrapper, in case they don't have access to a prebuilt one for whatever reason.
Any other views?
Regards,
/Pete
Closing this for now. If the users encounter issues with libusb-1.0.def file, then we can reopen.
I will ask in the libusb-devel mailing list as well. I understand that it is meant to make the DLL generated by MSVC to be compatible with MinGW compilers. So far I can see they are compatible but I am using 64bit Windows and I think it does not matter for 64bit Windows.
Actually I do not know if libusb_set_option() can be exported correctly for 32bit Windows (it is not needed for 64bit Windows as far as I know) because it takes variadic.
/c/work/libusb/libusb-1.0.24_bin/MinGW32/dll
$ echo -e "LIBRARY\nEXPORTS" > libusb-1.0.def; strings libusb-1.0.dll | grep libusb | grep @ | sort | sed -e "s/\(.*\)@\([0-9]*\)/ \1\n \1@\2 = \1/" >> libusb
-1.0.def
LIBRARY
EXPORTS
_libusb_alloc_streams
_libusb_alloc_streams@16 = _libusb_alloc_streams
_libusb_alloc_transfer
_libusb_alloc_transfer@4 = _libusb_alloc_transfer
_libusb_attach_kernel_driver
_libusb_attach_kernel_driver@8 = _libusb_attach_kernel_driver
_libusb_bulk_transfer
_libusb_bulk_transfer@24 = _libusb_bulk_transfer
_libusb_cancel_transfer
_libusb_cancel_transfer@4 = _libusb_cancel_transfer
_libusb_claim_interface
_libusb_claim_interface@8 = _libusb_claim_interface
_libusb_clear_halt
_libusb_clear_halt@8 = _libusb_clear_halt
_libusb_close
_libusb_close@4 = _libusb_close
_libusb_control_transfer
_libusb_control_transfer@32 = _libusb_control_transfer
_libusb_detach_kernel_driver
_libusb_detach_kernel_driver@8 = _libusb_detach_kernel_driver
_libusb_dev_mem_alloc
_libusb_dev_mem_alloc@8 = _libusb_dev_mem_alloc
_libusb_dev_mem_free
_libusb_dev_mem_free@12 = _libusb_dev_mem_free
_libusb_error_name
_libusb_error_name@4 = _libusb_error_name
_libusb_event_handler_active
_libusb_event_handler_active@4 = _libusb_event_handler_active
_libusb_event_handling_ok
_libusb_event_handling_ok@4 = _libusb_event_handling_ok
_libusb_exit
_libusb_exit@4 = _libusb_exit
_libusb_free_bos_descriptor
_libusb_free_bos_descriptor@4 = _libusb_free_bos_descriptor
_libusb_free_config_descriptor
_libusb_free_config_descriptor@4 = _libusb_free_config_descriptor
_libusb_free_container_id_descriptor
_libusb_free_container_id_descriptor@4 = _libusb_free_container_id_descriptor
_libusb_free_device_list
_libusb_free_device_list@8 = _libusb_free_device_list
_libusb_free_pollfds
_libusb_free_pollfds@4 = _libusb_free_pollfds
_libusb_free_ss_endpoint_companion_descriptor
_libusb_free_ss_endpoint_companion_descriptor@4 = _libusb_free_ss_endpoint_companion_descriptor
_libusb_free_ss_usb_device_capability_descriptor
_libusb_free_ss_usb_device_capability_descriptor@4 = _libusb_free_ss_usb_device_capability_descriptor
_libusb_free_streams
_libusb_free_streams@12 = _libusb_free_streams
_libusb_free_transfer
_libusb_free_transfer@4 = _libusb_free_transfer
_libusb_free_usb_2_0_extension_descriptor
_libusb_free_usb_2_0_extension_descriptor@4 = _libusb_free_usb_2_0_extension_descriptor
_libusb_get_active_config_descriptor
_libusb_get_active_config_descriptor@8 = _libusb_get_active_config_descriptor
_libusb_get_bos_descriptor
_libusb_get_bos_descriptor@8 = _libusb_get_bos_descriptor
_libusb_get_bus_number
_libusb_get_bus_number@4 = _libusb_get_bus_number
_libusb_get_config_descriptor
_libusb_get_config_descriptor@12 = _libusb_get_config_descriptor
_libusb_get_config_descriptor_by_value
_libusb_get_config_descriptor_by_value@12 = _libusb_get_config_descriptor_by_value
_libusb_get_configuration
_libusb_get_configuration@8 = _libusb_get_configuration
_libusb_get_container_id_descriptor
_libusb_get_container_id_descriptor@12 = _libusb_get_container_id_descriptor
_libusb_get_device
_libusb_get_device@4 = _libusb_get_device
_libusb_get_device_address
_libusb_get_device_address@4 = _libusb_get_device_address
_libusb_get_device_descriptor
_libusb_get_device_descriptor@8 = _libusb_get_device_descriptor
_libusb_get_device_list
_libusb_get_device_list@8 = _libusb_get_device_list
_libusb_get_device_speed
_libusb_get_device_speed@4 = _libusb_get_device_speed
_libusb_get_max_iso_packet_size
_libusb_get_max_iso_packet_size@8 = _libusb_get_max_iso_packet_size
_libusb_get_max_packet_size
_libusb_get_max_packet_size@8 = _libusb_get_max_packet_size
_libusb_get_next_timeout
_libusb_get_next_timeout@8 = _libusb_get_next_timeout
_libusb_get_parent
_libusb_get_parent@4 = _libusb_get_parent
_libusb_get_pollfds
_libusb_get_pollfds@4 = _libusb_get_pollfds
_libusb_get_port_number
_libusb_get_port_number@4 = _libusb_get_port_number
_libusb_get_port_numbers
_libusb_get_port_numbers@12 = _libusb_get_port_numbers
_libusb_get_port_path
_libusb_get_port_path@16 = _libusb_get_port_path
_libusb_get_ss_endpoint_companion_descriptor
_libusb_get_ss_endpoint_companion_descriptor@12 = _libusb_get_ss_endpoint_companion_descriptor
_libusb_get_ss_usb_device_capability_descriptor
_libusb_get_ss_usb_device_capability_descriptor@12 = _libusb_get_ss_usb_device_capability_descriptor
_libusb_get_string_descriptor_ascii
_libusb_get_string_descriptor_ascii@16 = _libusb_get_string_descriptor_ascii
_libusb_get_usb_2_0_extension_descriptor
_libusb_get_usb_2_0_extension_descriptor@12 = _libusb_get_usb_2_0_extension_descriptor
_libusb_get_version
_libusb_get_version@0 = _libusb_get_version
_libusb_handle_events
_libusb_handle_events@4 = _libusb_handle_events
_libusb_handle_events_completed
_libusb_handle_events_completed@8 = _libusb_handle_events_completed
_libusb_handle_events_locked
_libusb_handle_events_locked@8 = _libusb_handle_events_locked
_libusb_handle_events_timeout
_libusb_handle_events_timeout@8 = _libusb_handle_events_timeout
_libusb_handle_events_timeout_completed
_libusb_handle_events_timeout_completed@12 = _libusb_handle_events_timeout_completed
_libusb_has_capability
_libusb_has_capability@4 = _libusb_has_capability
_libusb_hotplug_deregister_callback
_libusb_hotplug_deregister_callback@8 = _libusb_hotplug_deregister_callback
_libusb_hotplug_get_user_data
_libusb_hotplug_get_user_data@8 = _libusb_hotplug_get_user_data
_libusb_hotplug_register_callback
_libusb_hotplug_register_callback@36 = _libusb_hotplug_register_callback
_libusb_init
_libusb_init@4 = _libusb_init
_libusb_interrupt_event_handler
_libusb_interrupt_event_handler@4 = _libusb_interrupt_event_handler
_libusb_interrupt_transfer
_libusb_interrupt_transfer@24 = _libusb_interrupt_transfer
_libusb_kernel_driver_active
_libusb_kernel_driver_active@8 = _libusb_kernel_driver_active
_libusb_lock_event_waiters
_libusb_lock_event_waiters@4 = _libusb_lock_event_waiters
_libusb_lock_events
_libusb_lock_events@4 = _libusb_lock_events
_libusb_open
_libusb_open@8 = _libusb_open
_libusb_open_device_with_vid_pid
_libusb_open_device_with_vid_pid@12 = _libusb_open_device_with_vid_pid
_libusb_pollfds_handle_timeouts
_libusb_pollfds_handle_timeouts@4 = _libusb_pollfds_handle_timeouts
_libusb_ref_device
_libusb_ref_device@4 = _libusb_ref_device
_libusb_release_interface
_libusb_release_interface@8 = _libusb_release_interface
_libusb_reset_device
_libusb_reset_device@4 = _libusb_reset_device
_libusb_set_auto_detach_kernel_driver
_libusb_set_auto_detach_kernel_driver@8 = _libusb_set_auto_detach_kernel_driver
_libusb_set_configuration
_libusb_set_configuration@8 = _libusb_set_configuration
_libusb_set_debug
_libusb_set_debug@8 = _libusb_set_debug
_libusb_set_interface_alt_setting
_libusb_set_interface_alt_setting@12 = _libusb_set_interface_alt_setting
_libusb_set_log_cb
_libusb_set_log_cb@12 = _libusb_set_log_cb
_libusb_set_pollfd_notifiers
_libusb_set_pollfd_notifiers@16 = _libusb_set_pollfd_notifiers
_libusb_setlocale
_libusb_setlocale@4 = _libusb_setlocale
_libusb_strerror
_libusb_strerror@4 = _libusb_strerror
_libusb_submit_transfer
_libusb_submit_transfer@4 = _libusb_submit_transfer
_libusb_transfer_get_stream_id
_libusb_transfer_get_stream_id@4 = _libusb_transfer_get_stream_id
_libusb_transfer_set_stream_id
_libusb_transfer_set_stream_id@8 = _libusb_transfer_set_stream_id
_libusb_try_lock_events
_libusb_try_lock_events@4 = _libusb_try_lock_events
_libusb_unlock_event_waiters
_libusb_unlock_event_waiters@4 = _libusb_unlock_event_waiters
_libusb_unlock_events
_libusb_unlock_events@4 = _libusb_unlock_events
_libusb_unref_device
_libusb_unref_device@4 = _libusb_unref_device
_libusb_wait_for_event
_libusb_wait_for_event@8 = _libusb_wait_for_event
_libusb_wrap_sys_device
_libusb_wrap_sys_device@12 = _libusb_wrap_sys_device
libusb_alloc_streams
libusb_alloc_streams@16 = libusb_alloc_streams
libusb_alloc_transfer
libusb_alloc_transfer@4 = libusb_alloc_transfer
libusb_attach_kernel_driver
libusb_attach_kernel_driver@8 = libusb_attach_kernel_driver
libusb_bulk_transfer
libusb_bulk_transfer@24 = libusb_bulk_transfer
libusb_cancel_transfer
libusb_cancel_transfer@4 = libusb_cancel_transfer
libusb_claim_interface
libusb_claim_interface@8 = libusb_claim_interface
libusb_clear_halt
libusb_clear_halt@8 = libusb_clear_halt
libusb_close
libusb_close@4 = libusb_close
libusb_control_transfer
libusb_control_transfer@32 = libusb_control_transfer
libusb_detach_kernel_driver
libusb_detach_kernel_driver@8 = libusb_detach_kernel_driver
libusb_dev_mem_alloc
libusb_dev_mem_alloc@8 = libusb_dev_mem_alloc
libusb_dev_mem_free
libusb_dev_mem_free@12 = libusb_dev_mem_free
libusb_error_name
libusb_error_name@4 = libusb_error_name
libusb_event_handler_active
libusb_event_handler_active@4 = libusb_event_handler_active
libusb_event_handling_ok
libusb_event_handling_ok@4 = libusb_event_handling_ok
libusb_exit
libusb_exit@4 = libusb_exit
libusb_free_bos_descriptor
libusb_free_bos_descriptor@4 = libusb_free_bos_descriptor
libusb_free_config_descriptor
libusb_free_config_descriptor@4 = libusb_free_config_descriptor
libusb_free_container_id_descriptor
libusb_free_container_id_descriptor@4 = libusb_free_container_id_descriptor
libusb_free_device_list
libusb_free_device_list@8 = libusb_free_device_list
libusb_free_pollfds
libusb_free_pollfds@4 = libusb_free_pollfds
libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_usb_device_capability_descriptor
libusb_free_ss_usb_device_capability_descriptor@4 = libusb_free_ss_usb_device_capability_descriptor
libusb_free_streams
libusb_free_streams@12 = libusb_free_streams
libusb_free_transfer
libusb_free_transfer@4 = libusb_free_transfer
libusb_free_usb_2_0_extension_descriptor
libusb_free_usb_2_0_extension_descriptor@4 = libusb_free_usb_2_0_extension_descriptor
libusb_get_active_config_descriptor
libusb_get_active_config_descriptor@8 = libusb_get_active_config_descriptor
libusb_get_bos_descriptor
libusb_get_bos_descriptor@8 = libusb_get_bos_descriptor
libusb_get_bus_number
libusb_get_bus_number@4 = libusb_get_bus_number
libusb_get_config_descriptor
libusb_get_config_descriptor@12 = libusb_get_config_descriptor
libusb_get_config_descriptor_by_value
libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value
libusb_get_configuration
libusb_get_configuration@8 = libusb_get_configuration
libusb_get_container_id_descriptor
libusb_get_container_id_descriptor@12 = libusb_get_container_id_descriptor
libusb_get_device
libusb_get_device@4 = libusb_get_device
libusb_get_device_address
libusb_get_device_address@4 = libusb_get_device_address
libusb_get_device_descriptor
libusb_get_device_descriptor@8 = libusb_get_device_descriptor
libusb_get_device_list
libusb_get_device_list@8 = libusb_get_device_list
libusb_get_device_speed
libusb_get_device_speed@4 = libusb_get_device_speed
libusb_get_max_iso_packet_size
libusb_get_max_iso_packet_size@8 = libusb_get_max_iso_packet_size
libusb_get_max_packet_size
libusb_get_max_packet_size@8 = libusb_get_max_packet_size
libusb_get_next_timeout
libusb_get_next_timeout@8 = libusb_get_next_timeout
libusb_get_parent
libusb_get_parent@4 = libusb_get_parent
libusb_get_pollfds
libusb_get_pollfds@4 = libusb_get_pollfds
libusb_get_port_number
libusb_get_port_number@4 = libusb_get_port_number
libusb_get_port_numbers
libusb_get_port_numbers@12 = libusb_get_port_numbers
libusb_get_port_path
libusb_get_port_path@16 = libusb_get_port_path
libusb_get_ss_endpoint_companion_descriptor
libusb_get_ss_endpoint_companion_descriptor@12 = libusb_get_ss_endpoint_companion_descriptor
libusb_get_ss_usb_device_capability_descriptor
libusb_get_ss_usb_device_capability_descriptor@12 = libusb_get_ss_usb_device_capability_descriptor
libusb_get_string_descriptor_ascii
libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii
libusb_get_usb_2_0_extension_descriptor
libusb_get_usb_2_0_extension_descriptor@12 = libusb_get_usb_2_0_extension_descriptor
libusb_get_version
libusb_get_version@0 = libusb_get_version
libusb_handle_events
libusb_handle_events@4 = libusb_handle_events
libusb_handle_events_completed
libusb_handle_events_completed@8 = libusb_handle_events_completed
libusb_handle_events_locked
libusb_handle_events_locked@8 = libusb_handle_events_locked
libusb_handle_events_timeout
libusb_handle_events_timeout@8 = libusb_handle_events_timeout
libusb_handle_events_timeout_completed
libusb_handle_events_timeout_completed@12 = libusb_handle_events_timeout_completed
libusb_has_capability
libusb_has_capability@4 = libusb_has_capability
libusb_hotplug_deregister_callback
libusb_hotplug_deregister_callback@8 = libusb_hotplug_deregister_callback
libusb_hotplug_get_user_data
libusb_hotplug_get_user_data@8 = libusb_hotplug_get_user_data
libusb_hotplug_register_callback
libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback
libusb_init
libusb_init@4 = libusb_init
libusb_interrupt_event_handler
libusb_interrupt_event_handler@4 = libusb_interrupt_event_handler
libusb_interrupt_transfer
libusb_interrupt_transfer@24 = libusb_interrupt_transfer
libusb_kernel_driver_active
libusb_kernel_driver_active@8 = libusb_kernel_driver_active
libusb_lock_event_waiters
libusb_lock_event_waiters@4 = libusb_lock_event_waiters
libusb_lock_events
libusb_lock_events@4 = libusb_lock_events
libusb_open
libusb_open@8 = libusb_open
libusb_open_device_with_vid_pid
libusb_open_device_with_vid_pid@12 = libusb_open_device_with_vid_pid
libusb_pollfds_handle_timeouts
libusb_pollfds_handle_timeouts@4 = libusb_pollfds_handle_timeouts
libusb_ref_device
libusb_ref_device@4 = libusb_ref_device
libusb_release_interface
libusb_release_interface@8 = libusb_release_interface
libusb_reset_device
libusb_reset_device@4 = libusb_reset_device
libusb_set_auto_detach_kernel_driver
libusb_set_auto_detach_kernel_driver@8 = libusb_set_auto_detach_kernel_driver
libusb_set_configuration
libusb_set_configuration@8 = libusb_set_configuration
libusb_set_debug
libusb_set_debug@8 = libusb_set_debug
libusb_set_interface_alt_setting
libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting
libusb_set_log_cb
libusb_set_log_cb@12 = libusb_set_log_cb
libusb_set_pollfd_notifiers
libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
libusb_setlocale
libusb_setlocale@4 = libusb_setlocale
libusb_strerror
libusb_strerror@4 = libusb_strerror
libusb_submit_transfer
libusb_submit_transfer@4 = libusb_submit_transfer
libusb_transfer_get_stream_id
libusb_transfer_get_stream_id@4 = libusb_transfer_get_stream_id
libusb_transfer_set_stream_id
libusb_transfer_set_stream_id@8 = libusb_transfer_set_stream_id
libusb_try_lock_events
libusb_try_lock_events@4 = libusb_try_lock_events
libusb_unlock_event_waiters
libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters
libusb_unlock_events
libusb_unlock_events@4 = libusb_unlock_events
libusb_unref_device
libusb_unref_device@4 = libusb_unref_device
libusb_wait_for_event
libusb_wait_for_event@8 = libusb_wait_for_event
libusb_wrap_sys_device
libusb_wrap_sys_device@12 = libusb_wrap_sys_device
MinGW.org gendef utility (I just found that MinGW.org is still alive from OSDN).
;
; Definition file of libusb-1.0.dll
; Automatic generated by gendef
; written by Kai Tietz 2008
;
LIBRARY "libusb-1.0.dll"
EXPORTS
GUID_DEVINTERFACE_LIBUSB0_FILTER DATA
GUID_DEVINTERFACE_USB_DEVICE DATA
GUID_DEVINTERFACE_USB_HOST_CONTROLLER DATA
GUID_DEVINTERFACE_USB_HUB DATA
active_contexts_list DATA
active_contexts_lock DATA
discovered_devs_append
htab_hash
libusb_alloc_streams@16
libusb_alloc_streams@16@16
libusb_alloc_transfer@4
libusb_alloc_transfer@4@4
libusb_attach_kernel_driver@8
libusb_attach_kernel_driver@8@8
libusb_bulk_transfer@24
libusb_bulk_transfer@24@24
libusb_cancel_transfer@4
libusb_cancel_transfer@4@4
libusb_claim_interface@8
libusb_claim_interface@8@8
libusb_clear_halt@8
libusb_clear_halt@8@8
libusb_close@4
libusb_close@4@4
libusb_control_transfer@32
libusb_control_transfer@32@32
libusb_detach_kernel_driver@8
libusb_detach_kernel_driver@8@8
libusb_dev_mem_alloc@8
libusb_dev_mem_alloc@8@8
libusb_dev_mem_free@12
libusb_dev_mem_free@12@12
libusb_error_name@4
libusb_error_name@4@4
libusb_event_handler_active@4
libusb_event_handler_active@4@4
libusb_event_handling_ok@4
libusb_event_handling_ok@4@4
libusb_exit@4
libusb_exit@4@4
libusb_free_bos_descriptor@4
libusb_free_bos_descriptor@4@4
libusb_free_config_descriptor@4
libusb_free_config_descriptor@4@4
libusb_free_container_id_descriptor@4
libusb_free_container_id_descriptor@4@4
libusb_free_device_list@8
libusb_free_device_list@8@8
libusb_free_pollfds@4
libusb_free_pollfds@4@4
libusb_free_ss_endpoint_companion_descriptor@4
libusb_free_ss_endpoint_companion_descriptor@4@4
libusb_free_ss_usb_device_capability_descriptor@4
libusb_free_ss_usb_device_capability_descriptor@4@4
libusb_free_streams@12
libusb_free_streams@12@12
libusb_free_transfer@4
libusb_free_transfer@4@4
libusb_free_usb_2_0_extension_descriptor@4
libusb_free_usb_2_0_extension_descriptor@4@4
libusb_get_active_config_descriptor@8
libusb_get_active_config_descriptor@8@8
libusb_get_bos_descriptor@8
libusb_get_bos_descriptor@8@8
libusb_get_bus_number@4
libusb_get_bus_number@4@4
libusb_get_config_descriptor@12
libusb_get_config_descriptor@12@12
libusb_get_config_descriptor_by_value@12
libusb_get_config_descriptor_by_value@12@12
libusb_get_configuration@8
libusb_get_configuration@8@8
libusb_get_container_id_descriptor@12
libusb_get_container_id_descriptor@12@12
libusb_get_device@4
libusb_get_device@4@4
libusb_get_device_address@4
libusb_get_device_address@4@4
libusb_get_device_descriptor@8
libusb_get_device_descriptor@8@8
libusb_get_device_list@8
libusb_get_device_list@8@8
libusb_get_device_speed@4
libusb_get_device_speed@4@4
libusb_get_max_iso_packet_size@8
libusb_get_max_iso_packet_size@8@8
libusb_get_max_packet_size@8
libusb_get_max_packet_size@8@8
libusb_get_next_timeout@8
libusb_get_next_timeout@8@8
libusb_get_parent@4
libusb_get_parent@4@4
libusb_get_pollfds@4
libusb_get_pollfds@4@4
libusb_get_port_number@4
libusb_get_port_number@4@4
libusb_get_port_numbers@12
libusb_get_port_numbers@12@12
libusb_get_port_path@16
libusb_get_port_path@16@16
libusb_get_ss_endpoint_companion_descriptor@12
libusb_get_ss_endpoint_companion_descriptor@12@12
libusb_get_ss_usb_device_capability_descriptor@12
libusb_get_ss_usb_device_capability_descriptor@12@12
libusb_get_string_descriptor_ascii@16
libusb_get_string_descriptor_ascii@16@16
libusb_get_usb_2_0_extension_descriptor@12
libusb_get_usb_2_0_extension_descriptor@12@12
libusb_get_version
libusb_get_version@0
libusb_handle_events@4
libusb_handle_events@4@4
libusb_handle_events_completed@8
libusb_handle_events_completed@8@8
libusb_handle_events_locked@8
libusb_handle_events_locked@8@8
libusb_handle_events_timeout@8
libusb_handle_events_timeout@8@8
libusb_handle_events_timeout_completed@12
libusb_handle_events_timeout_completed@12@12
libusb_has_capability@4
libusb_has_capability@4@4
libusb_hotplug_deregister_callback@8
libusb_hotplug_deregister_callback@8@8
libusb_hotplug_get_user_data@8
libusb_hotplug_get_user_data@8@8
libusb_hotplug_register_callback@36
libusb_hotplug_register_callback@36@36
libusb_init@8
libusb_init@4@8
libusb_interrupt_event_handler
libusb_interrupt_event_handler@4
libusb_interrupt_transfer@24
libusb_interrupt_transfer@24@24
libusb_kernel_driver_active@8
libusb_kernel_driver_active@8@8
libusb_lock_event_waiters
libusb_lock_event_waiters@4
libusb_lock_events@4
libusb_lock_events@4@4
libusb_open@8
libusb_open@8@8
libusb_open_device_with_vid_pid@12
libusb_open_device_with_vid_pid@12@12
libusb_pollfds_handle_timeouts@4
libusb_pollfds_handle_timeouts@4@4
libusb_ref_device@4
libusb_ref_device@4@4
libusb_release_interface@8
libusb_release_interface@8@8
libusb_reset_device@4
libusb_reset_device@4@4
libusb_set_auto_detach_kernel_driver@8
libusb_set_auto_detach_kernel_driver@8@8
libusb_set_configuration@8
libusb_set_configuration@8@8
libusb_set_debug@8
libusb_set_debug@8@8
libusb_set_interface_alt_setting@12
libusb_set_interface_alt_setting@12@12
libusb_set_log_cb@12
libusb_set_log_cb@12@12
libusb_set_option
libusb_set_pollfd_notifiers@16
libusb_set_pollfd_notifiers@16@16
libusb_setlocale@4
libusb_setlocale@4@4
libusb_strerror@4
libusb_strerror@4@4
libusb_submit_transfer@4
libusb_submit_transfer@4@4
libusb_transfer_get_stream_id@4
libusb_transfer_get_stream_id@4@4
libusb_transfer_set_stream_id@8
libusb_transfer_set_stream_id@8@8
libusb_try_lock_events@4
libusb_try_lock_events@4@4
libusb_unlock_event_waiters
libusb_unlock_event_waiters@4
libusb_unlock_events
libusb_unlock_events@4
libusb_unref_device@4
libusb_unref_device@4@4
libusb_wait_for_event@8
libusb_wait_for_event@8@8
libusb_wrap_sys_device@12
libusb_wrap_sys_device@12@12
load_system_library
usb_api_backend DATA
usbd_status_to_libusb_transfer_status
usbdk_backend DATA
usbi_add_event_source
usbi_alloc_device
usbi_alloc_event_data
usbi_arm_timer
usbi_backend DATA
usbi_clear_event
usbi_cond_timedwait
usbi_connect_device
usbi_create_event
usbi_create_timer
usbi_default_context DATA
usbi_destroy_event
usbi_destroy_timer
usbi_disarm_timer
usbi_disconnect_device
usbi_get_device_by_session_id
usbi_get_monotonic_time
usbi_handle_disconnect@4
usbi_handle_transfer_cancellation
usbi_handle_transfer_completion
usbi_hotplug_deregister
usbi_hotplug_match
usbi_hotplug_notification
usbi_io_exit
usbi_io_init
usbi_log
usbi_remove_event_source
usbi_sanitize_device
usbi_signal_event
usbi_signal_transfer_completion
usbi_wait_for_events
windows_error_str
windows_force_sync_completion
windows_version DATA
winusb_backend DATA
@pbatard Sorry Pete, need to disturb you to see what is the right way to export libusb_set_option(). Thanks.
Ref: the use of variadic poses some challenges for Python bindings. https://github.com/pyusb/pyusb/issues/200 https://github.com/vpelletier/python-libusb1/issues/75#issuecomment-909733308
what is the right way to export libusb_set_option()
Don't know if that helps but when compiling the libusb DLL using VS2019, you get a libusb-1.0.exp generated.
Then you can issue something like strings libusb-1.0.exp | grep _libusb | sort | uniq and you'll get:
_libusb_alloc_streams@16
_libusb_alloc_transfer@4
_libusb_attach_kernel_driver@8
_libusb_bulk_transfer@24
_libusb_cancel_transfer@4
_libusb_claim_interface@8
_libusb_clear_halt@8
_libusb_close@4
_libusb_control_transfer@32
_libusb_detach_kernel_driver@8
_libusb_dev_mem_alloc@8
_libusb_dev_mem_free@12
_libusb_error_name@4
_libusb_event_handler_active@4
_libusb_event_handling_ok@4
_libusb_exit@4
_libusb_free_bos_descriptor@4
_libusb_free_config_descriptor@4
_libusb_free_container_id_descriptor@4
_libusb_free_device_list@8
_libusb_free_pollfds@4
_libusb_free_ss_endpoint_companion_descriptor@4
_libusb_free_ss_usb_device_capability_descriptor@4
_libusb_free_streams@12
_libusb_free_transfer@4
_libusb_free_usb_2_0_extension_descriptor@4
_libusb_get_active_config_descriptor@8
_libusb_get_bos_descriptor@8
_libusb_get_bus_number@4
_libusb_get_config_descriptor@12
_libusb_get_config_descriptor_by_value@12
_libusb_get_configuration@8
_libusb_get_container_id_descriptor@12
_libusb_get_device@4
_libusb_get_device_address@4
_libusb_get_device_descriptor@8
_libusb_get_device_list@8
_libusb_get_device_speed@4
_libusb_get_max_iso_packet_size@8
_libusb_get_max_packet_size@8
_libusb_get_next_timeout@8
_libusb_get_parent@4
_libusb_get_pollfds@4
_libusb_get_port_number@4
_libusb_get_port_numbers@12
_libusb_get_port_path@16
_libusb_get_ss_endpoint_companion_descriptor@12
_libusb_get_ss_usb_device_capability_descriptor@12
_libusb_get_string_descriptor_ascii@16
_libusb_get_usb_2_0_extension_descriptor@12
_libusb_get_version@0
_libusb_handle_events@4
_libusb_handle_events_completed@8
_libusb_handle_events_locked@8
_libusb_handle_events_timeout@8
_libusb_handle_events_timeout_completed@12
_libusb_has_capability@4
_libusb_hotplug_deregister_callback@8
_libusb_hotplug_get_user_data@8
_libusb_hotplug_register_callback@36
_libusb_init@4
_libusb_interrupt_event_handler@4
_libusb_interrupt_transfer@24
_libusb_kernel_driver_active@8
_libusb_lock_events@4
_libusb_lock_event_waiters@4
_libusb_open@8
_libusb_open_device_with_vid_pid@12
_libusb_pollfds_handle_timeouts@4
_libusb_ref_device@4
_libusb_release_interface@8
_libusb_reset_device@4
_libusb_set_auto_detach_kernel_driver@8
_libusb_set_configuration@8
_libusb_set_debug@8
_libusb_set_interface_alt_setting@12
_libusb_setlocale@4
_libusb_set_log_cb@12
_libusb_set_option
_libusb_set_pollfd_notifiers@16
_libusb_strerror@4
_libusb_submit_transfer@4
_libusb_transfer_get_stream_id@4
_libusb_transfer_set_stream_id@8
_libusb_try_lock_events@4
_libusb_unlock_events@4
_libusb_unlock_event_waiters@4
_libusb_unref_device@4
_libusb_wait_for_event@8
_libusb_wrap_sys_device@12
So it seems variadic functions are exported as taking no parameters. Outside of that, I have literally no idea how they are meant to be handled. I would guess that despite having no parameter, there's a first param register that's always implicitly set to the number of variadic parameters, and, if non zero, there's a second param register that'll point to an array of params, but, really, that's a question to direct people who develop compilers, which I am not.
@pbatard I think that is the best guess for now.
The export from VS2019 seems to be easy to understand in most case, at a quick glance, I only see one strange point.
_libusb_get_port_number@4 --> this does not seem to be correct
_libusb_get_port_numbers@12
So in this case, the merged https://github.com/libusb/libusb/pull/964 may not be totally correct but it probably may not do harm as well. Let's see if people are encountering the issue or not.
With libusb-1.0.24 release, there is a reported issue. https://github.com/EttusResearch/uhd/issues/453
@pbatard If your guess is correct, how shall we fix the libusb-1.0.def? Is the following correct?
diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def
index e357ef5..648ae6a 100644
--- a/libusb/libusb-1.0.def
+++ b/libusb/libusb-1.0.def
@@ -155,7 +155,6 @@ EXPORTS
libusb_set_interface_alt_setting
libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting
libusb_set_option
- libusb_set_option@8 = libusb_set_option
libusb_set_pollfd_notifiers
libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
libusb_setlocale
Outside of trial and error I have very little idea on that topic.
The thing is, from the output I posted above, I see that functions with zero parameters are exported with @0 (e.g. _libusb_get_version@0), but variadics are exported without the any @something.
I'm afraid I do not know about the internals of Win32 DLL handling to be able to provide any kind of advice here. Sorry.
@pbatard You are being very helpful already. Thanks. Now the question is how to test. This issue report comes from https://github.com/EttusResearch/uhd/issues/453 and based on the testing it is a false alarm. That issue has been closed.
From libusb-devel mailing list. On Thu, Sep 9, 2021 at 9:53 PM Jef Driesen wrote:
On 5/09/2021 04:25, Xiaofan Chen wrote:
https://github.com/libusb/libusb/issues/944 Just wondering what is the right way to export libusb-1.0.def since it takes variadic.Thanks.
With the winapi (stdcall) calling convention, the function itself is responsible for cleaning up the stack at the end of the call. That is of course incompatible with varargs functions, because for such functions only the caller knows how many arguments were pushed on the stack. According to the documentation, the compiler switches to cdecl calling convention (the standard C calling convention) for such functions:
https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160 https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-160 https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-160
That explains why the libusb_set_option function doesn't get decorated with an @x suffix: it uses cdecl instead of stdcall.
x86-64 has its own calling convention (using registers).
Jef
I'll note that this is a compile time error on clang with MSYS2. Fixed with:
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -2181,7 +2181,7 @@ void API_EXPORTED libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb,
* on this platform
* \returns LIBUSB_ERROR_NOT_FOUND if LIBUSB_OPTION_USE_USBDK is valid on this platform but UsbDk is not available
*/
-int API_EXPORTED libusb_set_option(libusb_context *ctx,
+int _cdecl libusb_set_option(libusb_context *ctx,
enum libusb_option option, ...)
{
int arg = 0, r = LIBUSB_SUCCESS;
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 61cacc9..e0ba2b1 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -2126,7 +2126,7 @@ enum libusb_option {
LIBUSB_OPTION_MAX = 3
};
-int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...);
+int __cdecl libusb_set_option(libusb_context *ctx, enum libusb_option option, ...);
#if defined(__cplusplus)
}
-int API_EXPORTED libusb_set_option(libusb_context *ctx, +int _cdecl libusb_set_option(libusb_context *ctx, enum libusb_option option, ...) { int arg = 0, r = LIBUSB_SUCCESS;
not correct i think this is likley to cause the symbol not exported at all, it's is not enough for win/mac to export a symbol in a dll or dylib i suspect it's more the API_EXPORTED that is somehow not correct in case your using the header (not building fro source )
-int API_EXPORTED libusb_set_option(libusb_context *ctx, +int _cdecl libusb_set_option(libusb_context *ctx, enum libusb_option option, ...) { int arg = 0, r = LIBUSB_SUCCESS;
not correct i think this is likley to cause the symbol not exported at all, it's is not enough for win/mac to export a symbol in a dll or dylib i suspect it's more the API_EXPORTED that is somehow not correct in case your using the header (not building fro source )
Not sure what you mean. The dll has it:
strings libusb-1.0.dll | grep set_opt
windows_set_option
_libusb_set_option
libusb_set_option
_libusb_set_option
I'll note that this is a compile time error on clang with MSYS2. Fixed with:
--- a/libusb/core.c +++ b/libusb/core.c @@ -2181,7 +2181,7 @@ void API_EXPORTED libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, * on this platform * \returns LIBUSB_ERROR_NOT_FOUND if LIBUSB_OPTION_USE_USBDK is valid on this platform but UsbDk is not available */ -int API_EXPORTED libusb_set_option(libusb_context *ctx, +int _cdecl libusb_set_option(libusb_context *ctx, enum libusb_option option, ...) { int arg = 0, r = LIBUSB_SUCCESS; diff --git a/libusb/libusb.h b/libusb/libusb.h index 61cacc9..e0ba2b1 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -2126,7 +2126,7 @@ enum libusb_option { LIBUSB_OPTION_MAX = 3 }; -int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); +int __cdecl libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); #if defined(__cplusplus) }
Interesting that MSYS2 clang can capture this one. So basically you are saying LIBUSB_CALL (WINAPI or _stdcall under Windows) is not compatible with the varidic function libusb_set_option(), right? This is in line with what Jef Driesen mentioned in the libusb-devel mailing list.
Are you using 32bit or 64bit MSY2 clang? Supposedly _stdcall will be ignored by ARM32, ARM64 and AMD64 architecture.
And interestingly MSYS2 GCC does not have issues -- that was the compiler toolchain we recommend to use with libusb.
@mcuee 32-bit. That strings output was with a 32-bit library.
MSYS2 GCC behaves the same. The only difference is that it's a silent failure with GCC and explicit with clang.
@mcuee 32-bit. That strings output was with a 32-bit library.
MSYS2 GCC behaves the same. The only difference is that it's a silent failure with GCC and explicit with clang.
I see. BTW, how do you install MSYS2 clang32, it seems to me the toolchain is not ready yet. https://www.msys2.org/docs/environments/ https://issueexplorer.com/issue/msys2/MINGW-packages/9687
C:\msys64 has a clang32.exe