如何解决来自 Python BufferedIO 对象的 C `FILE` 流
我正在为需要 FILE *
句柄作为输入的 C 库函数编写 Python 绑定。
我希望 Python 调用者将一个打开的 io.BufferedReader
对象传递给函数,以便保留对句柄的控制,例如:
with open(fname,'rb') as fh:
my_c_function(fh)
我的 C 包装器大致如下所示:
PyObject *my_c_function (PyObject *self,PyObject *args)
{
FILE *fh;
if (! PyArgs_ParseTuple (args,"?",&fh)) return NULL;
my_c_lib_function (fh);
// [...]
}
显然,我不知道应该为 "?"
使用什么符号,或者我是否应该使用与 PyArgs_ParseTuple
不同的方法。
Python C API 文档似乎没有提供任何关于如何处理缓冲 IO 对象的示例(据我了解,Buffer 协议适用于字节对象和 co.... 对吗?)
似乎我可以在我的 C 包装器中查看 Python 句柄对象的文件描述符(就像调用 fileno()
)并使用 fdopen()
从中创建一个 C 文件句柄。
几个问题:
- 这是最方便的方式吗?还是 Python C API 中有我没有看到的内置方法?
-
fileno()
文档提到:“如果存在,则返回流的底层文件描述符(整数)。如果 IO 对象不使用文件描述符,则会引发 OSError。”在什么情况下会发生这种情况?如果我传递一个不是open()
在 Python 中创建的文件句柄怎么办? - 在 Python 打开的只读 fd 上打开只读 C 句柄似乎很安全,应该保证在 C 函数之后关闭句柄;但是,有人能想到这种方法有什么缺陷吗?
解决方法
不确定这是否是最合理的方式,但我在 Linux 中是通过以下方式解决的:
static PyObject *
get_fh_from_python_fh (PyObject *self,PyObject *args)
{
PyObject *buf,*fileno_fn,*fileno_obj,*fileno_args;
if (! PyArg_ParseTuple (args,"O",&buf)) return NULL;
// Get the file descriptor from the Python BufferedIO object.
// FIXME This is not sure to be reliable. See
// https://docs.python.org/3/library/io.html#io.IOBase.fileno
if (! (fileno_fn = PyObject_GetAttrString (buf,"fileno"))) {
PyErr_SetString (PyExc_TypeError,"Object has no fileno function.");
return NULL;
}
fileno_args = PyTuple_New(0);
if (! (fileno_obj = PyObject_CallObject (fileno_fn,fileno_args))) {
PyErr_SetString (PyExc_SystemError,"Error calling fileno function.");
return NULL;
}
int fd = PyLong_AsSize_t (fileno_obj);
/*
* From the Linux man page:
*
* > The file descriptor is not dup'ed,and will be closed when the stream
* > created by fdopen() is closed. The result of applying fdopen() to a
* > shared memory object is undefined.
*
* This handle must not be closed. Leave open for the Python caller to
* handle it.
*/
FILE *fh = fdopen (fd,"r");
// rest of the code...
}
这只是考虑到 Linux,但到目前为止它完成了它需要做的事情。更好的方法是深入了解 BufferedReader 对象,甚至可能在其中找到 FILE *
;但如果这不是 Python API 的一部分,它可能会在未来的版本中被破坏。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。