python - Python C API 的常量正确性

标签 python c++ python-c-api

看来Python C API 与字符数组的const 正确性不一致。例如,PyImport_ImportFrozenModule接受 char* , 而 PyImport_ImportModule接受 const char* .

所有这一切的含义是,在我使用嵌入式 Python 解释器编写的 C++ 应用程序中,有时我必须将传递给 Python API 调用的字符串文字转换为 char*。 (与 const char* 相对),有时我不这样做。例如:

PyObject *os = PyImport_ImportModule("os"); // Works without the const_cast
PyObject *cwd = PyObject_CallMethod(os, const_cast<char*>("getcwd"), NULL); // Accepts char*, not const char*

如果我不执行 const_cast<char*> (或 (char*) )在字符串文字上,我收到有关将字符串文字转换为 char* 的编译器警告.

这是我的问题:

  1. 让某些功能不采用 const char* 是否有优势/原因? (和/或为什么 Python API 在这方面不一致)?我的理解是,如果该函数可以采用字符串文字,则它无法更改 char*所以 const修饰符只会加强这一点。我也相信 const对于 C(为其编写 API)而言,区别并不像在 C++ 中那么重要(如果我错了请纠正我……我的强项是 python,而不是 C/C++)。 Python API 缺乏“const 正确性”是因为它在 C 中不那么重要吗? (有一个 old thread on the python mailing list 从 2000 年问同样的问题,但它似乎没有去任何地方,这暗示原因可能是由于一些编译器不支持 const 。由于许多函数现在有 const char* ,这似乎不再适用)
  2. 因为我对 C++ 的理解有限,所以我不确定我是否打算正确地转换字符串文字。在我看来,我可以执行以下任一操作(我目前正在执行第一个):

    // Method 1) Use const_cast<char*>
    PyImport_ImportFrozenModule(const_cast<char*>("mymodule"));
    
    // Method 2) Use (char*)
    PyImport_ImportFrozenModule((char*) "mymodule");
    
    // Method 3) Use char array
    char mod[] = "mymodule";
    PyImport_ImportFrozenModule(mod);
    

    哪种方法最好?


更新:

看起来 Python3 分支正在慢慢尝试修复 const 正确性问题。例如,PyImport_ImportFrozenModule我在上面用作示例的函数现在采用 const char*在 Python 3.4 中,但仍然有一些函数只需要 char* ,例如 PyLong_FromString .

最佳答案

根据来自 python-dev 的一些邮件列表对话,看起来最初的 API 只是在创建时没有考虑到 const 的正确性,可能只是因为 Guido 没有考虑到这一点。追溯到 2002 年,someone asked如果有任何希望通过添加 const-correctness 来解决这个问题,提示总是必须这样做很痛苦:

somefunc(const char* modulename, const char* key)
{
    ... PyImport_ImportModule(const_cast<char*>(modulename)) ...

Guido Van Rossum(Python 的创造者)replied (强调我的):

I've never tried to enforce const-correctness before, but I've heard enough horror stories about this. The problem is that it breaks 3rd party extensions left and right, and fixing those isn't always easy. In general, whenever you add a const somewhere, it ends up propagating to some other API, which then also requires a const, which propagates to yet another API needing a const, ad infinitum.

有更多的讨论,但没有 Guido 的支持,这个想法就夭折了。

一晃九年,话题又来了。这次有人只是想知道为什么有些函数是 const 正确的,而其他函数不是。 Python核心开发者之一replied with this :

We have been adding const to many places over the years. I think the specific case was just missed (i.e. nobody cared about adding const there).

似乎当它可以在不破坏向后兼容性的情况下完成时,const-correctness 已经被添加到 C API 的许多地方(对于 Python 3,在它的地方破坏了与 Python 2 的向后兼容性),但从来没有真正的全局努力来到处修复它。所以在 Python 3 中情况要好一些,但即使现在整个 API 也可能不是 const 正确的。

我认为 Python 社区没有任何首选方法来处理不正确的 const 调用的转换(官方 C-API style guide 中没有提及),可能是因为没有很多人通过 C++ 代码与 C-API 进行交互。不过,我会说,从纯 C++ 最佳实践的角度来看,首选的做法是首选。 (我绝不是 C++ 专家,所以对此持保留态度)。

关于python - Python C API 的常量正确性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20875520/

相关文章:

python - 类型错误 : 'NoneType' object has no attribute '__getitem__' tkinter error

python反Collat​​z猜想

python - 如何在 os walk Python 2.7 中跳过目录

c++ - 在 C++ 中优化二维数组

c++ - vector 中的不可复制元素

python - 如何获取当前的 PyInterpreterState?

python - CApi 中的 PyArg_ParseTuple 段错误

Python 3 : Convert decimals to date time

c++ - 在 SDI : where to disable menu, 代码在 MDI 中正常

python - 使用 C 将 numpy 数组对象拆分为两个不同大小的 vector