Mais conteúdo relacionado Semelhante a C python 原始碼解析 投影片 (10) Mais de kao kuo-tung (15) C python 原始碼解析 投影片3. 大綱
1. 介紹 C 語言如何模擬繼承
2. 介紹 python 的根本物件 PyObject
3. 介紹 PyType
4. 介紹 PyIntObject
5. 介紹 PyStringObject
6. 介紹 PyList
https://github.com/ya790206/CPython
6. int main(){
struct classA obj;
struct classA *pa = &obj;
struct classB *pb = (struct classB*)&obj;
struct classC *pc = (struct classC*)&obj;
obj.data = 0;
printf("%d, %d, %d, %d, %d, %dn", pa->data, pb->data[0], pb->data[1], pb-
>data[2], pb->data[3], pc->data);
obj.data = 1;
printf("%d, %d, %d, %d, %d, %dn", pa->data, pb->data[0], pb->data[1], pb-
>data[2], pb->data[3], pc->data);
obj.data = 1 << 8;
printf("%d, %d, %d, %d, %d, %dn", pa->data, pb->data[0], pb->data[1], pb-
>data[2], pb->data[3], pc->data);
printf("%p %pn",&(pb->data[1]) - &(((struct classB*)0)->data[1]), pb);
return 0;
}
7. 0, 0, 0, 0, 0, 0
1, 1, 0, 0, 0, 1
256, 0, 1, 0, 0, 256
0x7fff613428a0 0x7fff613428a0
9. #include <stdio.h>
typedef void (*myfunc)();
#define Father_HEADER
myfunc init;
struct father{
Father_HEADER
};
struct child1{
Father_HEADER
myfunc custom1;
};
struct child2{
Father_HEADER
myfunc custom2;
};
C 語言模仿繼承方法
10. void father_init(){
printf("call father initn");
}
void child1_init(){
printf("call child1 initn");
}
void child2_init(){
printf("call child2 initn");
}
void call_init(struct father *obj){
obj->init();
}
11. int main(){
struct father f_obj = {father_init};
struct child1 c1_obj = {child1_init, 0};
struct child2 c2_obj = {child2_init, 0};
call_init(&f_obj);
call_init((struct father*) &c1_obj);
call_init((struct father*) &c2_obj);
return 0;
}
13. object.h
Python 物件根本:
1. PyObject
a. 如 int
b. PyObject_HEAD
2. PyVarObject
a. 多了 ob_size 欄位
b. 如 string, list
c. PyObject_VAR_HEAD
ref: http://docs.python.org/2/c-api/structures.html
16. ob_refcnt:
1. Reference Counting
#define Py_INCREF(op) (
_Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA
((PyObject*)(op))->ob_refcnt++)
ob_type:
a. 該物件的 type,該物件能作的動作
b. PyType_Type 物件的此欄位指向自己
c. 其他屬於 PyTypeObject 的物件此欄位指向
PyType_Type 物件
d. 其他物件則指向他所屬的 PyTypeObject 物件
20. PyTypeObject
1. 存放該物件可以被執行的方法
2. 如 PyInt_Type 存放 Int 型別所支援的方法,他
支援 tp_str,所以我們可以使用 str(5)。當我們
呼叫 str(5),他會呼叫相對應的 c function,
int_to_decimal_string。
3. 因為 tp_call 的值是 0,因此 int 型別不能被呼
叫。tp_call 對應到 python 的 __call__ 方法。
23. PyIntObject
1. PyInt_FromLong(long ival) 建立整數的函數
2. 預設 CPython 實作,-5 ~ 256 的整數物件都
是 singletons。
3. 使用 free_list 來減少沒必的 memory
allocate/deallocate。
4. 每次向python memory system系統要求可容
納 N_INTOBJECTS 個整數的空間。
5. 做連續 n 次加法時,會產生 n - 1 個暫時物
件。因 int_add 的回傳值是 PyObject。
25. 1 2 3 4 5 6 7 8
free list: 6 -> 7 -> 8
如果在第三個位置的物件被刪除後
1 2 3 4 5 6 7 8
free list: 3 -> 6 -> 7 -> 8
31. why Py_REFCNT(s) -= 2?
1. 因為當 intern dict 的 key ,被加一
2. 又當 intern dict 的 value ,再被加一
3. 這兩個參考計數只被 intern dict使用,如果不
減2,則永遠不會被消滅。(至少有 intern dict
的 key/value 指向他)
33. string_concat
op = (PyStringObject *)PyObject_MALLOC(PyStringObject_SIZE + size);
PyObject_INIT_VAR(op, &PyString_Type, size);
op->ob_shash = -1;
op->ob_sstate = SSTATE_NOT_INTERNED;
Py_MEMCPY(op->ob_sval, a->ob_sval, Py_SIZE(a));
Py_MEMCPY(op->ob_sval + Py_SIZE(a), b->ob_sval, Py_SIZE(b));
op->ob_sval[size] = '0';
return (PyObject *) op;
1. 每次完成字串加法的動作後,傳回新的物件
2. 每次取得記憶體空間,是使用
PyObject_MALLOC
35. string_join
/* Allocate result space. */
res = PyString_FromStringAndSize((char*)
NULL, sz);
if (res == NULL) {
Py_DECREF(seq);
return NULL;
}
1. 只分配一次記憶體
36. /* Catenate everything. */
p = PyString_AS_STRING(res);
for (i = 0; i < seqlen; ++i) {
size_t n;
item = PySequence_Fast_GET_ITEM(seq, i);
n = PyString_GET_SIZE(item);
Py_MEMCPY(p, PyString_AS_STRING(item), n);
p += n;
if (i < seqlen - 1) {
Py_MEMCPY(p, sep, seplen);
p += seplen;
}
}
Py_DECREF(seq);
return res;
39. PyList_New
1. static PyListObject *free_list[PyList_MAXFREELIST];
2. nbytes = size * sizeof(PyObject *);
3. op = PyObject_GC_New(PyListObject, &PyList_Type);
4. op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);
1. op 用來維護 list 的相關資訊,如 ob_size, ob_refcnt
2. op->ob_item 存放 list 裡元素所在位址。
42. list_resize
1. new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
2. new_allocated += newsize;
3. PyMem_RESIZE(items, PyObject *, new_allocated);
4. self->ob_item = items;
5. Py_SIZE(self) = newsize;
6. self->allocated = new_allocated;
實際上,PyMem_RESIZE 最後呼叫 realloc。
Python 的 list行為與 C++ 的 vector 相似
44. ins1
if (where > n)
where = n;
items = self->ob_item;
for (i = n; --i >= where; )
items[i+1] = items[i];
Py_INCREF(v);
items[where] = v;
return 0;
45. 參考資料
1. python c api
2. Extending and Embedding the
Python Interpreter
3. Python源码剖析
4. python source code