4

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<char*> named “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...

1 Answer 1

3

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.

Specifically, you’ll need a PyTypeObject that corresponds to each PyObject-derived structure you intend to expose to the user – and so while a templated PyObject-derived LinkedList class may sound great at first, keep the PyTypeObject structure in mind (as your user-facing module representation will inevitably have to concretely define one or more of them) as well as which typename parameters upon which your LinkList ends up specialized.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.