私は C++ で Python 3 拡張機能を作成してPyObject
います。インスタンス レイアウトを定義する型 (構造体) に a が関連しているかどうかを確認する方法を見つけようとしています。PyObject
ではなく、 static-size にのみ興味がありますPyVarObject
。インスタンス レイアウトは、明確に定義された特定のレイアウト (必須PyObject
ヘッダーと (オプション) ユーザー定義メンバー) を持つ構造体によって定義されます。
以下は、Defining New Types のよく知られた Noddy の例にPyObject
基づく拡張の例です。
// Noddy struct specifies PyObject instance layout
struct Noddy {
PyObject_HEAD
int number;
};
// type object corresponding to Noddy instance layout
PyTypeObject NoddyType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"noddy.Noddy", /*tp_name*/
sizeof(Noddy), /*tp_basicsize*/
0, /*tp_itemsize*/
...
Noddy_new, /* tp_new */
};
Noddy
は型であり、コンパイル時のエンティティですがNoddyType
、実行時にメモリ内に存在するオブジェクトであることに注意してください。Noddy
との間の唯一の明らかな関係は、メンバーに格納されNoddyType
ている値のようです。sizeof(Noddy)
tp_basicsize
Python で実装された手書きの継承PyObject
は、特定の のインスタンス レイアウトを宣言するために使用される と タイプの間でキャストできるようにするルールを指定しPyObject
ます。
PyObject* Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
// When a Python object is a Noddy instance,
// its PyObject* pointer can be safely cast to Noddy
Noddy *self = reinterpret_cast<Noddy*>(type->tp_alloc(type, 0));
self->number = 0; // initialise Noddy members
return reinterpret_cast<PyObject*>(self);
}
さまざまなスロット関数のような状況では、「Python オブジェクトは Noddy である」と想定して、チェックなしでキャストしても問題ありません。ただし、他の状況でキャストする必要がある場合があり、ブラインド変換のように感じます。
void foo(PyObject* obj)
{
// How to perform safety checks?
Noddy* noddy = reinterpret_cast<Noddy*>(obj);
...
}
を確認することはできますがsizeof(Noddy) == Py_TYPE(obj)->tp_basicsize
、次の理由により解決策としては不十分です。
1) ユーザーが派生する場合Noddy
class BabyNoddy(Noddy):
pass
とのインスタンスへのポイントはobj
異なります。ただし、インスタンス レイアウト パーツへのポインターを取得するためにキャストしても安全です。foo
BabyNoddy
Py_TYPE(obj)->tp_basicsize
reinterpret_cast<Noddy*>(obj)
2) と同じサイズのインスタンス レイアウトを宣言する他の構造体が存在する可能性がありますNoddy
。
struct NeverSeenNoddy {
PyObject_HEAD
short word1;
short word2;
};
実際、C 言語レベルでは、構造体は型オブジェクトNeverSeenNoddy
と互換性があり、. したがって、キャストはまったく問題ありません。NoddyType
NoddyType
だから、私の大きな質問はこれです:
がインスタンス レイアウトPyObject
と互換性があるかどうかを判断するために使用できる Python ポリシーはありますか?Noddy
PyObject*
に埋め込まれているオブジェクト部分を指しているかどうかを確認する方法はありNoddy
ますか?
ポリシーではない場合、ハッキングの可能性はありますか?
編集:似ているように見える質問がいくつかありますが、私の意見では、私が尋ねたものとは異なります。例: PyObject の基になる構造体へのアクセス
EDIT2: Sven Marnach の回答を回答としてマークした理由を理解するには、その回答の下のコメントを参照してください。