Filename has to be encoded according to the system’s expected filename encoding before passing filenames to C library functions.
static PyObject* py_get_filename(PyObject* self, PyObject* args) { PyObject* bytes; char * filename; Py_ssize_t len; if (!PyArg_ParseTuple(args, "O&" , PyUnicode_FSConverter, &bytes)) { return NULL; } PyBytes_AsStringAndSize(bytes, &filename, &len); /* Use filename */ /* Cleanup and return */ Py_DECREF(bytes) Py_RETURN_NONE; } |
If there is already a existing PyObject *
that needs to be converted as a filename, then use the code given below :
Code#2 :
/* Object with the filename */ PyObject* obj; PyObject* bytes; char * filename; Py_ssize_t len; bytes = PyUnicode_EncodeFSDefault(obj); PyBytes_AsStringAndSize(bytes, &filename, &len); /* Use filename */ ... /* Cleanup */ Py_DECREF(bytes); |
If a filename is to be returned back to Python, use the following code given below –
Code #3 :
/* Turn a filename into a Python object */ char * filename; int filename_len; PyObject* obj = PyUnicode_DecodeFSDefaultAndSize( filename, filename_len); |
Dealing with filenames in a portable way is a tricky problem that is best left to Python. Filenames will be handled in a manner that, if one uses the above in extension C code.
Passing Open Files to C Extensions –
Code #4 : To convert a file to an integer file descriptor, use PyFile_FromFd()
PyObject* fobj; int fd = PyObject_AsFileDescriptor(fobj); if (fd < 0) { return NULL; } |
The resulting file descriptor is obtained by calling the fileno()
method on fobj. Thus, any object that exposes a descriptor in this manner should work (e.g., file, socket, etc.). A descriptor can be passed to various low-level C functions that expect to work with files. PyFile_FromFd()
is used to convert an integer file descriptor back into a Python object.
Code #5 :
/* Existing file descriptor (already open) */ int fd; PyObject* fobj = PyFile_FromFd(fd, "filename" , "r" , -1, NULL, NULL, NULL, 1); |
The arguments to PyFile_FromFd()
mirror those of the built-in open() function. NULL values simply indicate that the default settings for the encoding, errors, and newline arguments are being used.