在 C++ 中通过继承自定义 PyObject
Custom PyObject by inheritance in C++
长期 python 程序员,第一次 C++ 扩展编写者。无论如何,为了好玩,我正在尝试在 C++ 中为 python 创建一个链表模块。这是我的代码
#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 和 return 吗?现在有效的是:
import LinkedList
print "start"
l = LinkedList.new()
print "done"
但是当我在 python 中调用 l.get_value()
时,我得到了一个段错误。我知道我在做的事情可能是错误的,所以有人能给我指出正确的方向吗?
澄清一下,我知道在 linkedlist_new
函数完成后,名为“ll”的 LinkedList<char*>
被销毁,这是我遇到的问题的一部分。让我们假设我非常非常迷路...
首先:您可能需要手动设置 object header – 换句话说,更改
template <typename T>
class LinkedList : public PyObject { /* … */ }
类似于
template <typename T>
class LinkedList {
public:
PyObject_HEAD
/// …
}
…根据我自己的经验,后者有效,前提是 Python object 的 API 的其余部分填写正确。这是第二点:你没有定义一个 PyTypeObject
,它比你这里的要复杂一点(q.v。https://docs.python.org/2/c-api/typeobj.html)。
具体来说,您需要一个 PyTypeObject
对应于您打算向用户公开的每个 PyObject
派生结构 – 因此,模板化的 PyObject
派生 LinkedList
class 一开始听起来不错,请牢记 PyTypeObject
结构(因为您的 user-facing 模块表示将不可避免地必须具体定义其中的一个或多个)以及您的 LinkList
最终根据哪些 typename
参数专门化。
长期 python 程序员,第一次 C++ 扩展编写者。无论如何,为了好玩,我正在尝试在 C++ 中为 python 创建一个链表模块。这是我的代码
#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 和 return 吗?现在有效的是:
import LinkedList
print "start"
l = LinkedList.new()
print "done"
但是当我在 python 中调用 l.get_value()
时,我得到了一个段错误。我知道我在做的事情可能是错误的,所以有人能给我指出正确的方向吗?
澄清一下,我知道在 linkedlist_new
函数完成后,名为“ll”的 LinkedList<char*>
被销毁,这是我遇到的问题的一部分。让我们假设我非常非常迷路...
首先:您可能需要手动设置 object header – 换句话说,更改
template <typename T>
class LinkedList : public PyObject { /* … */ }
类似于
template <typename T>
class LinkedList {
public:
PyObject_HEAD
/// …
}
…根据我自己的经验,后者有效,前提是 Python object 的 API 的其余部分填写正确。这是第二点:你没有定义一个 PyTypeObject
,它比你这里的要复杂一点(q.v。https://docs.python.org/2/c-api/typeobj.html)。
具体来说,您需要一个 PyTypeObject
对应于您打算向用户公开的每个 PyObject
派生结构 – 因此,模板化的 PyObject
派生 LinkedList
class 一开始听起来不错,请牢记 PyTypeObject
结构(因为您的 user-facing 模块表示将不可避免地必须具体定义其中的一个或多个)以及您的 LinkList
最终根据哪些 typename
参数专门化。