문제

내 개체를 생성하고 삭제하기 위해 new 및 delete 연산자를 사용하고 싶습니다.

문제는 파이썬이 그것을 여러 단계로 나누는 것 같다는 것입니다.생성을 위한 tp_new, tp_init 및 tp_alloc 및 삭제를 위한 tp_del, tp_free 및 tp_dealloc.그러나 C++에는 객체를 할당하고 완전히 구성하는 new와 객체를 파괴하고 할당을 해제하는 delete가 있습니다.

Python tp_* 메소드 중 어떤 메소드를 제공해야 하며 어떻게 해야 합니까?

또한 C ++에서 직접 개체를 생성 할 수 있기를 원합니다. 또한이를 지원하기 위해 새로운 운영자에게 과부하가 필요합니까?

또한 Python에서 내 확장 유형을 서브클래싱할 수 있기를 원합니다. 이를 지원하기 위해 특별히 해야 할 일이 있습니까?

저는 파이썬 3.0.1을 사용하고 있습니다.

편집하다:좋아, tp_init는 내가 하고 있는 일에 비해 개체를 너무 변경 가능하게 만드는 것 같습니다. (예: Texture 개체를 가져오고 생성 후 내용을 변경하는 것은 괜찮지만 크기, 비트 수준 등과 같은 기본 측면을 변경하면 많은 문제가 발생합니다. 이러한 종류의 문제가 해결되었다고 가정하는 기존 C++ 항목).구현하지 않으면 생성된 후에 사람들이 __init__을 호출하는 것을 중지합니다(또는 적어도 튜플처럼 호출을 무시합니다).아니면 동일한 객체에서 tp_init가 두 번 이상 호출되는 경우 예외를 발생시키는 플래그가 있어야 합니까?

그 외에도 나머지 대부분은 정리된 것 같아요.

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()과 동일하며 refcnt를 1로 초기화합니다.Python에는 자체 할당자 PyType_GenericAlloc가 있지만 유형은 특수 할당자를 구현할 수 있습니다.

tp_new는 Python의 __new__와 동일합니다.일반적으로 데이터에 대한 포인터와 비교하여 데이터가 인스턴스 자체에 저장되는 불변 객체에 사용됩니다.예를 들어 문자열과 튜플은 char * 또는 PyTuple *을 사용하는 대신 인스턴스에 데이터를 저장합니다.

이 경우 tp_new는 입력 매개변수를 기반으로 필요한 메모리 양을 파악하고 tp_alloc을 호출하여 메모리를 가져온 다음 필수 필드를 초기화합니다.tp_new는 tp_alloc을 호출할 필요가 없습니다.예를 들어 캐시된 개체를 반환할 수 있습니다.

tp_init는 Python의 __init__과 동일합니다.대부분의 초기화는 이 함수에서 이루어져야 합니다.

__new__와 __init__의 차이점은 다음과 같습니다. 2단계 초기화, 또는 2단계 초기화.

당신은 "C++에 새로운 기능이 생겼습니다"하지만 그건 옳지 않아요.tp_alloc은 C++의 사용자 정의 경기장 할당자에 해당하고, __new__는 사용자 정의 유형 할당자(팩토리 함수)에 해당하며, __init__은 생성자와 더 유사합니다.마지막 링크에서는 C++와 Python 스타일 간의 유사점에 대해 자세히 설명합니다.

또한 읽어보세요 http://www.python.org/download/releases/2.2/descrintro/ __new__와 __init__이 어떻게 상호작용하는지 자세히 알아보세요.

"C++에서 직접 개체를 생성"하고 싶다고 썼습니다.최소한 개체 인스턴스화 중에 발생한 모든 Python 예외를 C++ 예외로 변환해야 하기 때문에 이는 다소 어렵습니다.이 작업에 대한 도움이 필요하면 Boost::Python을 살펴보세요.또는 2단계 초기화를 사용할 수 있습니다.;)

다른 팁

나는 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