I’m stuck passing a Python dictionary as argument to a Cython function, using libmtp libraries.
In the file test.py the connect_device() method works correctly, connects to the device, and returns a dictionary that maps the LIBMTP_mtpdevice_t struct, then I call the list_folders() method with the dictionary as argument.
I cast it again to the LIBMTP_mtpdevice_t type, inside the C function _list_folders() but when I pass it as an argument to the library’s function LIBMTP_get_folder_list(), the program crash with segmentation fault.
There is something I’m missinig, but I can’t figure out what.
I hope I was clear, I’m new to Cython and hope someone can help me to find the issue.
Thanks.
test.py
import mtp_manager as m
def run():
try:
print("nconnecting device...n")
dev = m.connect_device()
print("ndevice connected listing files and folders...n")
lst = m.list_folders(dev)
print("n printing list... n")
print(f"Folder list: {lst}")
except Exception as e:
print(e)
if __name__ == "__main__":
run()
mtp.pyx
def connect_device():
dev_d = None
LIBMTP_Init()
cdef LIBMTP_mtpdevice_t *device
device = LIBMTP_Get_First_Device()
if device is NULL:
print("No MTP devices found.")
return None
try:
dev_ext = {}
dev_ext['name'] = device.extensions.name.decode('utf-8')
dev_ext['major'] = device.extensions.major
dev_ext['minor'] = device.extensions.minor
dev_ext['next'] = <uintptr_t> device.extensions.next
dev_err = {}
dev_err['errornumber'] = device.errorstack.errornumber
dev_err['error_text'] = device.errorstack.error_text.decode('utf-8')
dev_err['next'] = <uintptr_t> device.errorstack.next
dev_storage = {}
dev_storage['id'] = device.storage.id
dev_storage['StorageType'] = device.storage.StorageType
dev_storage['FilesystemType'] = device.storage.FilesystemType
dev_storage['AccessCapability'] = device.storage.AccessCapability
dev_storage['MaxCapacity'] = device.storage.MaxCapacity
dev_storage['FreeSpaceInBytes'] = device.storage.FreeSpaceInBytes
dev_storage['FreeSpaceInObjects'] = device.storage.FreeSpaceInObjects
dev_storage['StorageDescription'] = device.storage.StorageDescription.decode('UTF-8')
dev_storage['VolumeIdentifier'] = device.storage.VolumeIdentifier.decode('UTF-8')
dev_storage['next'] = <uintptr_t>device.storage.next
dev_storage['prev'] = <uintptr_t>device.storage.prev
dev_d = {}
dev_d['object_bitsize'] = device.object_bitsize
dev_d['params'] = <void>device.params
dev_d['usbinfo'] = <void>device.usbinfo
dev_d['maximum_battery_level'] = device.maximum_battery_level
dev_d['default_text_folder'] = device.default_text_folder
dev_d['default_album_folder'] = device.default_album_folder
dev_d['default_music_folder'] = device.default_music_folder
dev_d['default_video_folder'] = device.default_video_folder
dev_d['default_picture_folder'] = device.default_picture_folder
dev_d['default_zencast_folder'] = device.default_zencast_folder
dev_d['default_playlist_folder'] = device.default_playlist_folder
dev_d['default_organizer_folder'] = device.default_organizer_folder
dev_d['cd'] = <void>device.cd
dev_d['cached'] = device.cached
dev_d['next'] = <uintptr_t>device.next
dev_d['extensions'] = dev_ext
dev_d['errorstack'] = dev_err
dev_d['storage'] = dev_storage
except Exception as e:
print(e)
return dev_d
def list_folders(device):
folders = _list_folders(<LIBMTP_mtpdevice_t*> device)
return folders
cdef _list_folders(LIBMTP_mtpdevice_t *device):
if not device:
raise TypeError
cdef LIBMTP_folder_t *folders
#SEGMENTATION FAULT
folders = LIBMTP_Get_Folder_List(device)
...