On Sun, Aug 29, 2010 at 4:52 AM, "Martin v. Löwis" <martin@v.loewis.de> wrote:
This is from tp_new and tp_dealloc, right? I think we should probably provide assessors PyObject_Alloc and PyObject_FreeObject.
Correct, and yes, that sounds like a good approach.
- PyObject_Print is used, but can't be supported, as it uses a FILE* parameter
I thought tp_print was supposed to have been removed.
Yes - that should have happened for 3.0. Not sure how to deal with it now.
tp_print actually is gone, but PyObject_Print was retained. It just relies on repr() and str() under the hood instead of the old tp_print slot. There are 4 operations performed on fp in that function: clearerr, ferror, fprintf and fwrite. There is also an implicit reference to errno (through PyErr_SetFromErrno) which can't be trusted in a mixed CRT world (PyErr_SetFromErrno() should be excluded from the Limited API, if it isn't already, and replaced with a PyErr_SetFromErrnoEx which takes the errno as an explicit argument. That assumes the CRTs will be sufficiently compatible that strerror() will give the correct answer for errno values from the other CRT. If that assumption is incorrect, the new function would also need to accept a string argument for the error description). Four options come to mind: - just leave it out of the limited API, extensions can do their own thing to print objects - leave PyObject_Print out of the limited API, but create a PyObject_PrintEx that takes a Python IO stream via PyObject* rather than a C level FILE*. - leave PyObject_Print out of the limited API, but create a PyObject_PrintEx that takes function pointers for the above 4 operations (so the FILE* pointer is only every operated on by functions from the extension module's CRT) - leave PyObject_Print out of the limited API, but create a PyObject_PRINT macro that does much the same thing with the logic rearranged so there is an inner function that figures out the string to be printed, but an outer macro that does all the operations on the FILE * object (so again, the FILE * is never passed to Python's CRT) The last option requires the fewest adjustments for extension authors, and it should be feasible to do it that way (even though it is a bit of a hack). Something along the lines of the following: #define PyObject_PRINT (obj, fp, flags, resultp) \ { \ int _result = -1; _t = _PyObject_PrintInner(obj, flags); \ if (_t != NULL) { \ clearerr(fp); \ fwrite(PyBytes_AS_STRING(_t), 1, PyBytes_GET_SIZE(_t), fp); \ Py_DECREF(_t); \ if (ferror(fp)) { \ PyErr_SetFromErrnoEx(PyExc_IOError, errno); \ clearerr(fp); \ } else { \ _result = 0; \ } \ } \ if (resultp != NULL) { \ *resultp = _result; \ } \ } Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia