I am moderately familiar with Python, but I am a beginner to C, C-extensions and IO Kit. I have read the C-extensions section of "Supporting Python 3", but might still be misunderstanding something fundamental.
I have a C-extension which works in Python 2, and I am trying to migrate it to Python 3. It uses Apple's IO Kit framework to detect some information about a USB device connected to an Apple computer. Here is the code which works in Python 2:
static PyObject * devGetDescriptor(PyObject *self, PyObject *args) {
storedState_t *ss = NULL;
PyObject *cobj = NULL;
byte_t buf[256];
IOUSBDevRequest request;
IOReturn err;
byte_t idx = kUSBDeviceDesc;
if(!PyArg_ParseTuple(args, "O!|b", &PyCObject_Type, &cobj, &idx)) {
return NULL;
}
ss = PyCObject_AsVoidPtr(cobj);
// populate the request
request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard,
kUSBDevice);
request.bRequest = kUSBRqGetDescriptor;
request.wValue = (idx << 8) | 0;
request.wIndex = 0;
request.wLength = 255;
request.pData = buf;
// do it
err = (*ss->dev)->DeviceRequest(ss->dev, &request);
if(err) return IOKIT_EXCEPTION(err);
// copy the result to caller
return PyString_FromStringAndSize((char*)buf, buf[0]);
}
Here is the definition for storedState_t
:
typedef struct
{
IOUSBDeviceInterface245 **dev;
// ...
} storedState_t;
Here is my attempt at converting it to code which works in Python 3, it causes a seg fault:
static PyObject * devGetDescriptor(PyObject *self, PyObject *args) {
storedState_t *ss = NULL;
PyObject *cobj = NULL;
byte_t buf[256];
IOUSBDevRequest request;
IOReturn err;
byte_t idx = kUSBDeviceDesc;
if (!PyArg_ParseTuple(args, "O|b", &cobj, &idx))
{
return NULL;
}
ss = PyCapsule_New(cobj, NULL, NULL); // changed to PyCapsule
// populate the request
request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard,
kUSBDevice);
request.bRequest = kUSBRqGetDescriptor;
request.wValue = (idx << 8) | 0;
request.wIndex = 0;
request.wLength = 255;
request.pData = buf;
// do it
err = (*ss->dev)->DeviceRequest(ss->dev, &request); // Causes Seg Fault
if (err)
return IOKIT_EXCEPTION(err);
// copy the result to caller
return PyUnicode_FromStringAndSize((char *)buf, buf[0]);
}
I believe the problem is with the line err = (*ss->dev)->DeviceRequest(ss->dev, &request);
. I know seg fault means one of the memory locations trying to be accessed in invalid, but I don't know which one is invalid nor how to fix it.