Python C api中的绝大多数函数其参数和返回值中包含PyObject*。这指针类型指向一个可以表示任何Python对象的不透明的数据结构。所有的Python对象在多数情况下以相同的方式对待。
所有的Python对象(甚至是Python的整数)都包含一个类型和引用计数。一个对象的类型决定了其是一个整数、列表、用户自定义函数还是其他。
引用计数对Python非常重要,引用计数必须显式地操作(通过Py_INCREF()、 Py_DECREF()等)。
本文:
-
PyObject
-
PyVarObject
-
PyTypeObject
PyObject
Include/object.h 提供了比较详细的注释。
Python2.7
#define PyObject_HEAD \
Py_ssize_t ob_refcnt; \
struct _typeobject *ob_type;
typedef struct _object {
PyObject_HEAD
} PyObject;
Python3.2
typedef struct _object {
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
#define PyObject_HEAD PyObject ob_base;
PyObject 是有两个成员的结构体,引用计数、对象类型:
其类型分别为 Py_ssize_t 和 struct _typeobject
Py_ssize_t
Py_ssize_t 是一个所占字节数与 size_t 相同的有符号的整数类型(C99中没有定义ssize_t这种类型,某些编译器比如gcc扩展有该类型)。关于该类型的一个介绍见PEP
353。
源码位于:Include/pyport.h
#ifdef HAVE_SSIZE_T
typedef ssize_t Py_ssize_t;
#elif SIZEOF_VOID_P == SIZEOF_SIZE_T
typedef Py_intptr_t Py_ssize_t;
#else
# error "Python needs a typedef for Py_ssize_t in pyport.h."
#endif
其中,Py_intptr_t 是可以存放指针的整数类型(C99中定义有 intptr_t),在不支持intptr_t的环境下,它是int、long或long long的别名。
PyVarObject
可变大小的容器对象
与PyObject相比,它多了一个成员:
- ob_refcnt
- ob_type
- ob_size
其中:ob_size 是元素的数目,而不是所需的字节的数目。
Python2.7
#define PyObject_VAR_HEAD \
PyObject_HEAD \
Py_ssize_t ob_size; /* Number of items in variable part */
typedef struct {
PyObject_VAR_HEAD
} PyVarObject;
Python3.2
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
#define PyObject_VAR_HEAD PyVarObject ob_base;
3个宏用来获取这3个成员的值
#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
PyTypeObject
每一个PyObject第二个成员是都是一个类型对象(PyTypeObject)。PyTypeObject本身是也一个PyVarObject
额,这个东西太复杂了,一堆堆的函数指针,看不懂。
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
void *tp_reserved; /* formerly known as tp_compare */
reprfunc tp_repr;
...
} PyTypeObject;
tp_name
|
类型的字符串名,比如"str" "int" ...
|
tp_basicsize
|
tp_basesize + tp_tiemsize * ob_size
|
tp_itemsize
|
tp_doc
|
文档字符串
|
创建与析构?
tp_alloc
|
tp_new
|
tp_init
|
tp_del
|
tp_free
|
tp_dealloc
|
C API函数和这些函数指针的对应关系(调用关系):
C API函数
|
PyTypeObject
中的函数指针
|
Python表达式
|
PyObject_Print(PyObject*,FILE*,int)
|
tp_print
tp_str
tp_repr
|
|
PyObject_Repr(PyObject*)
|
tp_repr
|
repr(o)
|
PyObject_Str(PyObject*v)
|
tp_str
|
str(o)
|
PyObject_Hash(PyObject*)
|
tp_hash
|
hash(o)
|
PyObject_GetAttr(PyObject*,PyObject*)
|
tp_getattr
tp_getattro
|
o.attr_name
|
PyObject_CallMethod(PyObject*,char*,...)
|
tp_call
|
o.method(...)
|
...
|
|
|
参考
分享到:
相关推荐
《Python源码剖析》共两部分,是一部分析Python的好书,通过学习《Python源码剖析》,你不想精通Python都难啊! 第0章 Python源码剖析--编译Python 0.1 Python总体架构 0.2 Python源代码的组织 0.3 Windows环境下...
《Python源码剖析》共两部分,是一部分析Python的好书,通过学习《Python源码剖析》,你不想精通Python都难啊! 第0章 Python源码剖析--编译Python 0.1 Python总体架构 0.2 Python源代码的组织 0.3 Windows环境下...
问题 你想在C中安全的执行某个Python调用并返回结果给C。 例如,你想在C语言中使用某个Python函数作为一个回调。 解决方案 在C语言中调用Python非常简单,不过涉及到...double call_func(PyObject *func, double x,
java中jython操作把python数据类型转成java类型 例如list->List dict->Map set->Set 以及一些基本操作的包装整合
2. 为每个模块的每一个函数增加一个型如PyObject* Module_func()的包装函数。 3. 为每个模块增加一个型如PyMethodDef ModuleMethods[]的数组。 4. 增加模块初始化函数void initModule() 假设具有以下三个C语言函数...
所有对象都有一些相同的东西, 源码中定义为PyObject和PyVarObject, 两个定义都有一个共同的头部定义PyObject_HEAD(其实PyVarObject有自己的头部定义PyObject_VAR_HEAD, 但其实际上用的也是PyObject_HEAD). 源码位置:...
把python嵌入的C++里面需要做...在了解下面的函数之前有必要了解一下**PyObject***指针,python里面几乎所有的对象都是使用这个指针来指示的。 Py_Initialize()&&Py_Finalize() 在调用任何python的c函数之前需要
在Python源码中,每一个对象都是一个结构体表示,都有一个计数字段。 typedef struct_object { int ob_refcnt; struct_typeobject *ob_type; } PyObject; PyObject是每个对象必有的内容,其中ob_refcnt就是作为...
派生PyO3的FromPyObject和IntoPy<PyObject>特性的宏。 派生的实现将Python的字典转换为Rust结构并返回。 用法 将库与Cargo.toml一起添加到您的Cargo.toml中: [dependencies] pyo3 = "0.9" dict_derive = "0.2.0" ...
本文实例讲述了Python中的is和id用法。分享给大家供大家参考。具体分析如下: (ob1 is ob2) 等价于 (id(ob1) == id(ob2)) 首先id函数可以获得对象的内存地址,如果两个对象的内存地址是一样的,那么这两个对象肯定是...
在python内存管理中,有一个block的概念。它比较类似于SGI次级空间配置器。 首先申请一块大的空间(4KB),然后把它切割成一小份(8, 16 一直到512)。 当有内存申请的请求时候,简单的流程是:根据大小找到对应的...
Python最主要和绝大多数时候用的都是引用计数,每一个PyObject定义如下: #define PyObject_HEAD \ Py_ssize_t ob_refcnt; \ struct _typeobject *ob_type; typedef struct _object { PyObject_HEAD } PyObject; ...
和is是等价的。Python源代码为证。 static PyObject * cmp_outcome(int op, register PyObject *v, register PyObject *w) { int res = 0; switch (op) { case PyCmp_IS: res = (v == w); break; case ...
简单来说python的内存管理机制有三种 ...在Python中每一个对象的核心就是一个结构体PyObject,它的内部有一个引用计数 ob_refcnt,当python的某个对象引用计数为0。就说明没有任何引用指向该对象,该对
Python是解释性语言, 底层就是用c实现的, 所以用python调用C是很容易的, 下面就总结一下各种调用的方法, 给出例子, 所有例子都在ubuntu9.10, python2.6下试过. 1. Python 调用 C (base) 想在python中调用c函数, 如...
整数对象在Python内部用PyIntObject结构体表示: typedef struct { PyObject_HEAD long ob_ival; } PyIntObject; PyObject_HEAD宏中定义的两个属性分别是: int ob_refcnt; struct _typeobject *ob_type; 这两个...
你要写C扩展来读取来自任何Python类文件对象中的数据(比如普通文件、StringIO对象等)。 解决方案 要读取一个类文件对象的数据,你需要重复调用 read() 方法,然后正确的解码获得的数据。 下面是一个C扩展函数例子...
怎样将C中的字符串转换为Python字节或一个字符串对象? 解决方案 C字符串使用一对 char * 和 int 来表示, 你需要决定字符串到底是用一个原始字节字符串还是一个Unicode字符串来表示。 字节对象可以像下面这样使用 ...
很不错了以个款游戏的服务器代码有兴趣自己看