友人と私は最近、さまざまな Python C++ ラッパーをいじり回しており、いくつかの専門的なプロジェクトと趣味のプロジェクトの両方のニーズを満たすものを見つけようとしています。Python C api の最も醜い部分を隠しながら、軽量であることとインターフェイスが簡単であることのバランスが取れているため、私たちは両方ともPyCxxに磨きをかけてきました。ただし、PyCxx は型の公開に関してはそれほど堅牢ではありません (つまり、コンストラクターを実装するのではなく、型ファクトリを作成するように指示します)。私たちは型をより機能的な方法で公開するためにギャップを埋めることに取り組んできました。 . これらのギャップを埋めるために、C API に目を向けます。
しかし、これにより、いくつかの疑問が残りました。API のドキュメントではあまり詳しく説明されていないようです (また、説明されている場合、答えが矛盾する場合があります)。基本的な包括的な質問は次のとおりです: Python 型が基本型として機能するには、何を定義する必要がありますか? PyCxx クラスが型として機能するためには、tp_new と tp_dealloc を明示的に定義し、型をモジュール属性として設定する必要があることがわかりました。私たちはまだ暗闇の中で手探りしていること。
これまでのコードは次のとおりです。
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'
それは私のがらくたを混乱させます。それを継承すると、基本クラスが完全に隠されているようです。私たちが欠けているものについて誰かが洞察を提供できれば、それはありがたいです! ありがとう!
編集: オーケー、これを投稿してから約 5 秒後に、以前に試してみたかったことを思い出しました。次のコードをキティに追加しました-
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
だからまだ助けを探しています!ありがとう!