2015-12-13 114 views
4

長期的python程序員,第一次是C++擴展編寫者。無論如何,爲了好玩,我試圖在C++中爲python創建一個鏈表模塊。這是我的代碼通過C++繼承自定義PyObject

#include <python2.7/Python.h> 
#include <iostream> 

using namespace std; 

template <typename T> 
class LinkedList : public PyObject { 
private: 
    struct ListNode { 
    ListNode(T value, ListNode* next) 
     : value(value), next(next) {} 
    T value; 
    ListNode* next; 
    }; 
    ListNode* head; 

public: 
    LinkedList(T value) 
    : head(new ListNode(value, 0)) { 
    cout << "class constructed" << endl; 
    Py_INCREF(this); 
    } 
    void get_value() { 
    cout << "test" << endl; 
    } 
    ~LinkedList() { 
    delete head; 
    Py_DECREF(this); 
    cout << "class destructed" << endl; 
    } 
}; 

static PyObject* linkedlist_new(PyObject* self, PyObject* args) { 
    LinkedList<char*> ll("hello"); 
    return Py_BuildValue("O", &ll); 
} 

static PyMethodDef LinkedListMethods[] = { 
    {"new", linkedlist_new, METH_VARARGS, 
    "Create a new linked list."}, 
    {NULL, NULL, 0, NULL} 
}; 

extern "C" PyMODINIT_FUNC initLinkedList(void) { 
    (void) Py_InitModule("LinkedList", LinkedListMethods); 
} 

我可以這樣做嗎?大多數文檔都是針對C的,但是我可以從PyObject繼承並像這樣返回它嗎?現在做什麼工作的權利,這是:

import LinkedList 

print "start" 
l = LinkedList.new() 
print "done" 

,但只要我打電話l.get_value()在Python中,我得到一個段錯誤。我知道我正在做的事情可能是錯誤的,那麼任何人都會如此善意地將我指向正確的方向?

而爲了澄清,我知道名爲「ll」的LinkedList<char*>linkedlist_new函數完成後被銷燬,這是我遇到的問題的一部分。讓我們只是假設我非常,非常失落......

回答

3

第一關:您可能需要手動設置對象頭 - 換句話說,改變

template <typename T> 
class LinkedList : public PyObject { /* … */ } 

喜歡的東西

template <typename T> 
class LinkedList { 
    public: 
     PyObject_HEAD 
     /// … 
} 

......在我自己的經驗後者工作,只要其餘的Python對象的API被正確填寫。這是第二點:你沒有定義一個PyTypeObject,這比你在這裏有更多的參與(q.v. https://docs.python.org/2/c-api/typeobj.html)。

具體來說,你需要一個PyTypeObject對應於要暴露給用戶的每個PyObject衍生結構 - 等而模板PyObject派生LinkedList類聽起來偉大在第一,牢記PyTypeObject結構(因爲您面向用戶的模塊表示將不可避免地必須具體定義其中的一個或多個)以及您的LinkList最終專用的參數。