2012-08-02 4 views
1

파이썬에서 호출하기 위해 C++ 클래스 주위에 씬 래퍼를 작성하려고합니다. 특정 문제는 virtual의 주석 처리가 해제되어 Foo()을 만들려고 할 때 인터프리터와 충돌합니다. 나는이 코드를 Boost :: python, SWIG 또는 Pyxxx로 다시 작성하여이 문제를 해결하는 것에 관심이 없다.이 라이브러리는 문제의 원인이 무엇인지 알기를 원하는 훨씬 더 큰 시스템의 추출물이다. 나는 그것을 어떻게 구현하는지 알고 싶다. 확장 모듈을 설정하고 시스템에 타입을 등록하면 파이썬 인터프리터의 호출은 아무런 문제없이 작동합니다. extern "C"을 사용하거나 클래스의 정적 멤버가 파이썬 타입의 슬롯에 등록하는 것만으로도 문제가 없습니다.파이썬 확장판에서 C++ 가상 멤버를 호출 할 때 크래시가 발생합니다.

멤버를 가상으로 선언 한 다음 파이썬 인터프리터에서 호출 할 때이를 호출하면 잘못된 메모리 액세스로 인해 크래시가 발생합니다. 액세스 된 주소는 클래스 멤버를 포인터로 인쇄하면 얻을 수있는 오프셋입니다. 따라야 할 특정 코드가 있지만 기본적인 질문은 : Python에 의해 호출 된 C 런타임 환경에서 가상 클래스 멤버 함수의 발송을 방해합니까? 파이썬은 v2.6.7이고 C++ 확장은 GCC 4.2.1에 의해 컴파일됩니다. Boost :: python이이를 지원한다고하는 관련 질문이 있습니다. 직접적으로 그것을 수행하거나 클래스 멤버 함수를 통해 시뮬레이션하는 것입니까?

// PythonType is a class that inherits from PyTypeObject and fills in defaults ... 

extern "C" int initHook(PyObject *self, PyObject *args, PyObject *kwds); 
class Foo 
{ 
public: 
static PythonType thePyType; 
    static void registerType(PyObject *module) 
    { 
    thePyType.tp_init = initHook; 
    PyType_Ready(&thePyType); 
    PyModule_AddObject(module, thePyType.tp_name, (PyObject*)&thePyType); 
    } 

    /*virtual*/ void insert() 
    { 
    printf("Inserted\n"); 
    } 
}; 
PythonType Foo::thePyType("Foo",sizeof(Foo)); 
extern "C" { 
    int initHook(PyObject *self, PyObject *args, PyObject *kwds) 
    { 
    ((Foo*)self)->insert(); 
    } 
} 
+0

나는 파이썬 바인딩 작업에 대해 잘 모릅니다.하지만 이처럼 C++ 오브젝트를 확실히 캐스팅 할 수는 없습니다. –

답변

0

감사합니다. Let ^e_Be, 귀하의 의견은 올바른 길로 나를 밀었습니다. 문제는 Foo 객체의 메모리가 파이썬 인터프리터에 의해 malloc되고 있다는 것입니다. 이것은 초기화 된 vtable에 의존하지 않기 때문에 다른 코드에서 문제를 일으키지 않았습니다. 가장 쉬운 해결책은 실제로 호출되는의 ctor을 보장하기 위해 배치 새로운를 사용하는 것입니다 후 가상 멤버는 제대로 작동합니다

int initHook(PyObject *self, PyObject *args, PyObject *kwds) 
{ 
    new(self) Foo(); 
    ((Foo*)self)->insert(); 
} 

On VTable pointers and malloc에서 더 자세한 Q & A가 있습니다.

+2

PyObject * 위에 새로운 배치를 사용하고 있고, 그 메모리 위치에서 완전히 다른 타입을 초기화하고 있습니까? CPython은 그것을 어떻게 관리해야합니까? – mfontanini

+0

PyTypeObject는 알 수없는 정보를 전달합니다. size 필드는이 알려지지 않은 구조에 대해 충분한 공간을 malloc 할 수 있도록합니다. PyObject *는 실제로 PyObject를위한 것이 아니라,이 미지의 구조체가 할당되어이 타입으로 전달됩니다. 파이썬 확장 코드는 포인터를 실제 타입으로 캐스트하여 사용합니다. – Amoss

관련 문제