当我使用Python3的C API构建PyObject时,它的ob_type为NULL

时间:2017-03-21 05:31:20

标签: python python-3.x c++11 python-c-api

我在C ++ 11中运行了这样的代码:

PyObject* aa = PyLong_FromLong(7L);

然后我检查了aa的值,它不是NULL,但是aa->ob_typeNULL

然而,当我跑:

PyObject* aa = PyLong_FromLong(257L);

aa->ob_type 不再 NULL了。我阅读了PyLong_FromLong的文档,发现了这个:

PyObject* PyLong_FromLong(long v)
Return value: New reference. 
Return a new PyLongObject object from v, or NULL on failure.

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object. So it should be possible to change the value of 1. I suspect the behaviour of Python in this case is undefined. :-)

似乎在-5到256之间构建PyLongObject时会遇到此问题。但我不明白原因。

更重要的是,这个问题不会出现在Python2中。那太不可思议了!

1 个答案:

答案 0 :(得分:0)

您还没有初始化Python。由于这些小对象是特殊的,因此在初始化Python时会设置它们。

#include <Python.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
  Py_Initialize();
  PyObject* aa = PyLong_FromLong(7L);
  printf("aa=%d\naa->ob_type=%p\n",PyLong_AsLong(aa),aa->ob_type);
  Py_Finalize();
  return 0;
}

正确打印

  

aa=7

     

aa->ob_type=0x7f380d6b5800(请注意,这会因运行而异)

如果我评论Py_Initialize()Py_Finalize(),那么我会遇到分段错误,但如果我不尝试使用PyLong_AsLong读取值,那么我会得到一个空指针ob_type

The documentation会告诉您初始化解释器。

对于Python2,它有两个整数类型PyIntPyLongPyInt处理小值,因此具有特殊的表格。如果在Python2中使用PyInt,您可能会看到同样的问题。在调用Py_Initialize之前用Python做的任何事情都是未定义的,所以它可能会以不同的方式失败。