2011-12-16 48 views
11

Tôi đang viết phần mở rộng C đầu tiên của mình cho Python và bị nhầm lẫn về số lượng tham chiếu của mình. Đây là những gì tôi đang cố gắng làm.trong phần mở rộng Python C

tôi cư một dict trong một vòng lặp for:

mydict = PyDict_New(); 

for (...) 
{ 
    pair = PyTuple_Pack(2, PyString_FromString("some string"), 
      PyString_FromString("some other string")); 

    /* at this point, the refcnt for the tuple is 1, the refcnts for the 
     2 string items are 2. Because according to the source, PyString_FromString 
     does an INCREF, and PyTuple_Pack() does an INCREF on its items 
    */ 

    PyDict_SetItem(mydict, PyString_FromString("some key"), pair); 

    /* At this point, the key's refcnt is 2. PyString_FromString sets it to 1 and 
     PyDict_SetItem INCREF's it. Ditto for pair since PyDict_SetItem also INCREF's 
     the value. 
    */ 

    Py_DECREF(pair); 

    /* pair's refcnt is 1 which makes sense to me since mydict now owns the tuple, 
     but the refcnt for its items are still at 2. I don't understand this part. 
    */ 
} 

return mydict; 

Are đếm ref của tôi có đúng không? Trong tài liệu C API, nó đặc biệt khuyên bạn nên sử dụng các hàm PyObject_FromXXX làm đối số cho PyTuple_SetItem hoặc PyList_SetItem vì chúng "lấy cắp" tham chiếu.

Nó không được ghi nhận liệu PyDict_SetItem có đánh cắp tài liệu tham khảo hay không. Tôi đoán nó không trong trường hợp này, Tôi nên làm

first = PyString_FromString("some string"); 
second = PyString_FromString("some other string"); 
pair = PyTuple_Pack(2, first, second); 
Py_DECREF(second); 
Py_DECREF(first); 

Tôi có đúng không?

+0

Câu hỏi này dường như liên quan: http://stackoverflow.com/questions/6977161/where-should-i-put-py-incref- và-py-decref-on-this-block-in-python-c-extension – Daenyth

+0

Có liên quan nhưng không trùng lặp: PyTuple vs PyDict – gecco

Trả lời

3

Nếu bạn nhìn vào mã nguồn CPython (Objects/tupleobject.c) cho PyTuple_Pack, bạn sẽ thấy rằng nó thực sự làm tăng số lượng tham chiếu trên mỗi đối tượng được đóng gói. Nếu bạn thay vì làm một PyTuple_New theo sau là các lệnh gọi PyTuple_SetItem, bạn sẽ không cần phải giảm số lượng tham chiếu vì SetItem đánh cắp các tham chiếu.

Cuối cùng, bạn có thể chỉ muốn sử dụng Py_BuildValue ("(ss)", "một số chuỗi", "một số chuỗi khác"); Nó sẽ xây dựng tuple của bạn cho bạn và nó sẽ tạo ra PyStrings cho bạn: http://docs.python.org/c-api/arg.html#Py_BuildValue

Các vấn đề liên quan