似乎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*
。
以下是我的问题:
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*
,这似乎不再适用了)因为我对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
函数现在在Python 3.4中使用const char*
,但仍然只有char*
的函数,例如PyLong_FromString
答案 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
- 所以如果你必须选择我会去那。但是,实际上,我不会对此感到困扰。