• 15.17 传递文件名给C扩展
    • 问题
    • 解决方案
    • 讨论

    15.17 传递文件名给C扩展

    问题

    你需要向C库函数传递文件名,但是需要确保文件名根据系统期望的文件名编码方式编码过。

    解决方案

    写一个接受一个文件名为参数的扩展函数,如下这样:

    1. static PyObject *py_get_filename(PyObject *self, PyObject *args) {
    2. PyObject *bytes;
    3. char *filename;
    4. Py_ssize_t len;
    5. if (!PyArg_ParseTuple(args,"O&", PyUnicode_FSConverter, &bytes)) {
    6. return NULL;
    7. }
    8. PyBytes_AsStringAndSize(bytes, &filename, &len);
    9. /* Use filename */
    10. ...
    11.  
    12. /* Cleanup and return */
    13. Py_DECREF(bytes)
    14. Py_RETURN_NONE;
    15. }

    如果你已经有了一个 PyObject * ,希望将其转换成一个文件名,可以像下面这样做:

    1. PyObject *obj; /* Object with the filename */
    2. PyObject *bytes;
    3. char *filename;
    4. Py_ssize_t len;
    5.  
    6. bytes = PyUnicode_EncodeFSDefault(obj);
    7. PyBytes_AsStringAndSize(bytes, &filename, &len);
    8. /* Use filename */
    9. ...
    10.  
    11. /* Cleanup */
    12. Py_DECREF(bytes);
    13.  
    14. If you need to return a filename back to Python, use the following code:
    15.  
    16. /* Turn a filename into a Python object */
    17.  
    18. char *filename; /* Already set */
    19. int filename_len; /* Already set */
    20.  
    21. PyObject *obj = PyUnicode_DecodeFSDefaultAndSize(filename, filename_len);

    讨论

    以可移植方式来处理文件名是一个很棘手的问题,最后交由Python来处理。如果你在扩展代码中使用本节的技术,文件名的处理方式和和Python中是一致的。包括编码/界面字节,处理坏字符,代理转换和其他复杂情况。

    原文:

    http://python3-cookbook.readthedocs.io/zh_CN/latest/c15/p17_pass_filenames_to_c_extensions.html