gpt4 book ai didi

python - 使用 PyCxx 创建可继承的 Python 类型

转载 作者:太空宇宙 更新时间:2023-11-03 15:29:41 24 4
gpt4 key购买 nike

我和一个 friend 最近一直在研究各种 Python C++ 包装器,试图找到一个既能满足一些专业项目又能满足业余爱好项目需求的包装器。我们都专注于 PyCxx作为轻量级和易于交互之间的良好平衡,同时隐藏了 Python C api 的一些最丑陋的部分。然而,PyCxx 在公开类型方面并不是非常健壮(即:它指示您创建类型工厂而不是实现构造函数),我们一直在努力填补空白以便以更实用的方式公开我们的类型.为了填补这些空白,我们求助于 C api。

这给我们留下了一些问题,然而,api 文档似乎没有涵盖太多深度(即使有,答案有时也会相互矛盾)。基本的首要问题很简单:必须定义什么才能使 Python 类型充当基类型?我们发现,要使 PyCxx 类作为一种类型运行,我们需要显式定义 tp_new 和 tp_dealloc 并将类型设置为模块属性,并且我们需要在 [our type]->tp_flags 上设置 Py_TPFLAGS_BASETYPE,但超出我们仍在黑暗中摸索。

到目前为止,这是我们的代码:

class kitty : public Py::PythonExtension<kitty> {
public:
kitty() : Py::PythonExtension<kitty>() {}
virtual ~kitty() {}

static void init_type() {
behaviors().name("kitty");
add_varargs_method("speak", &kitty::speak);
}

static PyObject* tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) {
return static_cast<PyObject*>(new kitty());
}

static void tp_dealloc(PyObject *obj) {
kitty* k = static_cast<kitty*>(obj);
delete k;
}

private:
Py::Object speak(const Py::Tuple &args) {
cout << "Meow!" << endl;
return Py::None();
}
};

// cat Module
class cat_module : public Py::ExtensionModule<cat_module> {
public:
cat_module() : Py::ExtensionModule<cat_module>("cat") {

kitty::init_type();

// Set up additional properties on the kitty type object
PyTypeObject* kittyType = kitty::type_object();
kittyType->tp_new = &kitty::tp_new;
kittyType->tp_dealloc = &kitty::tp_dealloc;
kittyType->tp_flags |= Py_TPFLAGS_BASETYPE;

// Expose the kitty type through the module
module().setAttr("kitty", Py::Object((PyObject*)kittyType));

initialize();
}
virtual ~cat_module() {}
};

extern "C" void initcat() {
static cat_module* cat = new cat_module();
}

我们的 Python 测试代码如下所示:

import cat

class meanKitty(cat.kitty):
def scratch(self):
print "hiss! *scratch*"

myKitty = cat.kitty()
myKitty.speak()

meanKitty = meanKitty()
meanKitty.speak()
meanKitty.scratch()

奇怪的是,如果你注释掉所有的 meanKitty 位,脚本运行并且猫喵喵叫就好了,但是如果你取消注释 meanKitty 类,Python 突然给我们这个:

AttributeError: 'kitty' object has no attribute 'speak'

这让我很困惑。就好像从它继承完全隐藏了基类!如果有人可以提供一些关于我们所缺少的东西的见解,我们将不胜感激!谢谢!


编辑:好的,所以在发布这篇文章后大约五秒钟,我想起了我们之前想尝试的事情。我将以下代码添加到 kitty -

virtual Py::Object getattr( const char *name ) {
return getattr_methods( name );
}

现在我们用 Python 对两只小猫喵喵叫!然而,仍然没有完全实现,因为现在我明白了:

Traceback (most recent call last):
File "d:\Development\Junk Projects\PythonCxx\Toji.py", line 12, in <module>
meanKitty.scratch()
AttributeError: scratch

所以还在寻求帮助!谢谢!

最佳答案

您必须声明 kitty作为class new_style_class: public Py::PythonClass< new_style_class > .参见 simple.cxx Python 测试用例位于 http://cxx.svn.sourceforge.net/viewvc/cxx/trunk/CXX/Demo/Python3/ .

Python 2.2 引入了新式类,除其他外,它允许用户对内置类型(如新的内置类型)进行子类化。继承在您的示例中不起作用,因为它定义了一个旧式类。

关于python - 使用 PyCxx 创建可继承的 Python 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/548442/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com