修正了Python C API的正确性

时间:2014-01-02 02:38:06

标签: 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中根本不那么重要? (2000年有一个old thread on the python mailing list提出了同样的问题,但它似乎没有去任何地方,并且暗示原因可能是由于某些编译器不支持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);
    

    哪种方法最好用?


  3. 更新

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

2 个答案:

答案 0 :(得分:4)

基于来自python-dev的一些邮件列表对话,看起来初始API只是简单地创建时考虑到了const的正确性,可能只是因为Guido没有想到它。一直追溯到2002年,someone asked如果有任何希望通过添加常量来解决这个问题,抱怨说总是要做到这一点很痛苦:

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

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

  

我从来没有尝试过强制执行正确性,但我听说过   关于这一点的恐怖故事。问题是它打破了第3名   左右派对扩展,修复这些扩展并不容易。   通常,无论何时在某处添加const,它都会传播   到某些其他API,然后还需要传播的const   另一个需要const,无限的API。

还有一些讨论,但如果没有Guido的支持,这个想法就会消失。

快进九年,这个话题又来了。这次有人只是想知道为什么有些函数是const-correct,而有些则不是。 Python核心开发人员之一replied with this

  

多年来,我们一直在向很多地方添加const。我觉得   特定情况刚刚错过(即没有人关心添加const   有)。

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

我不认为Python社区有任何首选的方法来处理非const的调用 - 正确(在官方中没有提到它) C-API style guide),可能是因为没有人在C ++代码中与C-API接口。我会说,从纯C ++最佳实践角度来看,首选的方法是首选。 (我绝不是C ++专家,所以请稍等一下。)

答案 1 :(得分:3)

  

是否有一些优势/理由让某些功能不采用const char*

没有。看起来像是对图书馆设计的疏忽,或者像你说的那样,遗留问题。但他们至少可以使它保持一致!

  

我的理解是,如果函数可以采用字符串文字,则不能更改char*,因此const修饰符只会加强这一点。

完全。他们的文档还应该指定函数调用期间不应修改函数参数(或者更确切地说,参数的指针对象);唉,目前还没有这么说。

  

我还认为const区别对于C(编写API)的重要性不如C ++中那么重要。

嗯,不是真的,至少据我所知。

  

我看到它的方式,我可以是以下任何一种(我现在正在做第一次)

(好)

  

哪种方法最好用?

const_cast至少会确保你修改const - 所以如果你必须选择我会去那。但是,实际上,我不会对此感到困扰。