質問

私は新しいを使用して、私のオブジェクトを作成し、破壊するための演算子を削除したい。

問題は、Pythonでいくつかの段階にそれを破るようです。 tp_new、破壊のための創造とtp_del、tp_freeとtp_deallocためtp_initとtp_alloc。しかし、C ++だけ割り当て、完全にオブジェクトを作成し、破棄され、削除やオブジェクトの割り当てを解除した新しいています。

のpython tp_ *メソッドのどちら私が提供する必要があると彼らは何をしなければならないのか。

また、私はC ++などで直接オブジェクトを作成できるようにしたい「PyObject * OBJ =新しいMyExtensionObject(引数);」私もこれをサポートするために、いくつかの方法で、new演算子をオーバーロードする必要がありますか?

私もPythonで私の拡張タイプをサブクラス化できるようにしたいと思い、私はこれをサポートするために必要な特別なものはありますか?

私は、Python 3.0.1を使用しています。

編集: [OK]を、tp_initは私がやっている何のためのオブジェクトは少しも可変させるように思われる(例えばなど、作成は結構です後に内容を変更、テクスチャオブジェクトを取るが、そのようなサイズ、それの基本的な側面を変更、bitdeptの多くを中断します物事のこれらの並べ替えを前提として既存のC ++のもの)が固定されています。私はいけない場合、それは単に人々がその構築には、AFTER __init__の呼び出し(またはタプルがないように、少なくとも、呼び出しを無視する)を停止します実装します。または私はtp_initが同じオブジェクト上で複数回呼び出された場合、例外または気にいらをスローいくつかのフラグを持っている必要がありますか?

それとは別に、私は、IVEが残りソートのほとんどを得たと考えています。

extern "C"
{
    //creation + destruction
    PyObject* global_alloc(PyTypeObject *type, Py_ssize_t items)
    {
        return (PyObject*)new char[type->tp_basicsize + items*type->tp_itemsize];
    }
    void global_free(void *mem)
    {
        delete[] (char*)mem;
    }
}
template<class T> class ExtensionType
{
    PyTypeObject *t;
    ExtensionType()
    {
        t = new PyTypeObject();//not sure on this one, what is the "correct" way to create an empty type object
        memset((void*)t, 0, sizeof(PyTypeObject));
        static PyVarObject init = {PyObject_HEAD_INIT, 0};
        *((PyObject*)t) = init;

        t->tp_basicsize = sizeof(T);
        t->tp_itemsize  = 0;

        t->tp_name = "unknown";

        t->tp_alloc   = (allocfunc) global_alloc;
        t->tp_free    = (freefunc)  global_free;
        t->tp_new     = (newfunc)   T::obj_new;
        t->tp_dealloc = (destructor)T::obj_dealloc;
        ...
    }
    ...bunch of methods for changing stuff...
    PyObject *Finalise()
    {
    ...
    }
};
template <class T> PyObjectExtension : public PyObject
{
...
    extern "C" static PyObject* obj_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
    {
        void *mem = (void*)subtype->tp_alloc(subtype, 0);
        return (PyObject*)new(mem) T(args, kwds)
    }
    extern "C" static void obj_dealloc(PyObject *obj)
    {
        ~T();
        obj->ob_type->tp_free(obj);//most of the time this is global_free(obj)
    }
...
};
class MyObject : PyObjectExtension<MyObject>
{
public:
    static PyObject* InitType()
    {
        ExtensionType<MyObject> extType();
        ...sets other stuff...
        return extType.Finalise();
    }
    ...
};
役に立ちましたか?

解決

これらのドキュメントは http://docs.python.org/であります3.0 / C-API / typeobj.html http://docs.python.org/3.0/extending/newtypes.htmlする独自のタイプを作成する方法について説明します。

tp_allocは、例えば、低レベルのメモリ割り当てを行います。これは)(malloc関数と等価である、プラス1のPythonにREFCNTを初期化し、それ自身のアロケータ、PyType_GenericAllocを持っていますが、タイプは、特殊なアロケータを実装することができます。

tp_newはPythonの__new__と同じです。これは通常、データへのポインタと比較したデータが、インスタンス自体に記憶されている不変のオブジェクトのために使用されます。例えば、文字列やタプルではなくCHAR *またはPyTuple *を使用する、インスタンスにそのデータを格納する。

このケースでは、tp_newは、基本的なフィールドを初期化し、入力パラメータに基づいて、必要とされているどのくらいのメモリ割り出し、およびメモリを取得するためにtp_allocを呼び出します。 tp_newはtp_allocを呼び出す必要はありません。それは、例えば、キャッシュされたオブジェクトを返すことができます。

tp_initはPythonの__init__と同じです。あなたの初期化のほとんどは、この関数にする必要があります。

__new__と__init__間の区別は/ <二段階の初期化と呼ばれていますA>、または<のhref = "http://groups.google.com/group/comp.lang.python/browse_thread/thread/b129dc656f4d0c8b/e43ae56909c3c00a?lnk=gst&q=two-phase+init#e43ae56909c3c00a" のrel =」 noreferrer ">二相初期化する

あなたが言う "のC ++を単にの新しいを持っている" が、それは正しくありません。 tp_allocは__new__は、カスタム・タイプ・アロケータ(ファクトリ関数)に対応し、__init__よりコンストラクタに似て、C ++でカスタムアリーナアロケータに対応します。その最後のリンクは、C ++とPythonのスタイル間の類似点について詳しく説明します。

また、 http://www.python.org/download/releases/2.2を読みます/ descrintro / の方法__new__と__init__相互作用の詳細については。

あなたがしたいことを書く「Cで直接オブジェクトを作成++」。少なくとも、あなたがC ++例外へのオブジェクトのインスタンス化中に発生したPythonの例外を変換する必要がありますので、それはかなり難しいです。この作業でいくつかの助けのためのPython ::ブーストを見てみてください。それとも、二相の初期化を使用することができます。 ;)

他のヒント

私は全くのPython APIを知らないが、Pythonは割り当てと初期化を分割する場合は、新しい配置を使用することができる必要があります。

例えば:ます。

 // tp_alloc
 void *buffer = new char[sizeof(MyExtensionObject)];
 // tp_init or tp_new (not sure what the distinction is there)
 new (buffer) MyExtensionObject(args);
 return static_cast<MyExtensionObject*>(buffer);

 ...
 // tp_del
 myExtensionObject->~MyExtensionObject(); // call dtor
 // tp_dealloc (or tp_free? again I don't know the python apis)
 delete [] (static_cast<char*>(static_cast<void*>(myExtensionObject)));
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top