James Robert Albert James Robert Albert - 2 months ago 11
C++ Question

Custom PyObject by inheritance in C++

Long term python programmer, first time C++ extension writer guy. Anyways, for fun, I'm trying to create a linked list module for python in C++. Here's my code

#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);
}


Can I do this? Most of the docs are for C, but can I inherit from PyObject and return it like this? What works right now is this:

import LinkedList

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


but as soon as I call l.get_value() in python, I get a segfault. I know that what I'm doing is probably wrong so would anybody be so kind as to point me into the right direction?

And for clarification, I know the LinkedList ll is destroyed after the linkedlist_new function is done which is part of the problem I'm having. Let's just assume I'm very, very lost...

Answer

First off: you may need to manually set up your object header – in other words, change

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

to something like

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

… in my own experience the latter works, provided the rest of the Python object’s API is filled out properly. Which is the second point: you don’t define a PyTypeObject, which is a little more involved (q.v. https://docs.python.org/2/c-api/typeobj.html) than what you have here.

Comments