2015-12-13 79 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最终专用的参数。