2012-12-04 2 views
3

부스트 파이썬을 사용하여 C++로 객체를 생성하고이를 파이썬에 전달하는 방법을 알아 내려고하고 있습니다. 나는 이것을 처리했지만 가비지 콜렉션이 발생하지는 않는다.부스트와 함께 파이썬에 C++ 객체 전달하기

클래스 A가 C++의 어딘가에 정의되어 있다고 상상해보십시오. passNewAToPython() 함수는 A 객체를 생성 한 다음 Python의 콜백 함수에 전달하는 코드의 다른 곳에서 호출됩니다. 나는 특정 인스턴스가 이제 newA 콜백이 호출 나중에 후 약간의 시간을 상상 따라서 PTR의 사용()

static PyObject * pythonCallbacks; 

void passNewAToPython() 
{ 
    A * a = new A(); 
    PyGILState_STATE _GILState = PyGILState_Ensure(); 
    //Should really use a try catch here too but lets ignore that for now 
    boost::python::call_method<void>(pythonCallbacks, "newA", boost::python::ptr(a)); 
    PyGILState_Release(_GILState); 
} 

void initmodule(PyObject* userCallCallbacks_) 
{ 
    PyEval_InitThreads(); 

    pythonCallbacks = userCallCallbacks_; 
} 

BOOST_PYTHON_MODULE(mymodule) 
{ 
    def("initmodule", initmodule); 

    class_<A, boost::noncopyable>("A", init<>()); 
} 

파이썬 코드

import mymodule 

class pythonCallbacks(object): 
    a_list = []; 
    def newA(self, a): 
     self.a_list.append(a) 

callbacks = pythonCallbacks() 
mymodule.initmodule(callbacks) 

을 사본을 파이썬에 통과하지합니다. 인스턴스를 저장할 유일한 장소는 a_list에 있습니다. 따라서 a_list에서 a를 삭제하면 new로 생성 한 객체에서 C++ 삭제가 호출 될 것으로 예상됩니다. 그런 일은 결코 일어나지 않으므로 물건을 새어 나옵니다.

저는이 작업을 수행하는 데 다양한 기법을 시도했지만 모든 작업을 관리하지 못했습니다. 아마도 위의 예제를 수정하는 방법을 보여주는 완전한 예제를 정말 고맙게 생각할 것입니다.

+0

내가 파이썬 :: 부스트에 익숙하지 해요,하지만 당신은 어디에서 온 파이썬 객체 참조 횟수를 해제됩니다

class_<A, shared_ptr<A>, boost:noncopyable>("A", init<>()); 

그런 다음 당신은 당신의 공장 기능이 작업을 수행 할 수 있습니다 C++ 쪽? – Arafangion

+0

C++ 측에서 어떻게 파이썬 객체 참조 카운트를 해제합니까? 참조 횟수를 늘리거나 줄이기위한 BOOST 및 Python API 명령을 모두 보았지만 파이썬 개체에서만 작동합니다. 여기에 파이썬 객체가 call_method 함수에서 생성됩니다. call_method가 완료된 후에 나는 모든 파이썬 참조가 사라졌을 때 객체가 삭제되도록 객체에 대한 유일한 참조가 파이썬을 통해 존재하기를 원합니다. 나는 boost :: python :: object를 포인터에서 꺼내고 그 위로 증가/감소를 호출하려고 시도했지만 일반적으로 충돌이 발생합니다. – Dave

+1

그래서 개체의 소유권을 이전하고 있습니다.이 경우 대상 메서드가 참조 횟수를 증가시키지 않으면 참조 횟수를 감소시켜야합니다. – Arafangion

답변

0

나는 ptr()이 가리키는 대상의 수명과 아무 관련이 없다고 확신합니다. 평생을 관리한다면 전적으로 당신에게 달려 있습니다. (나는 그것이 PyCObject를 사용처럼 사용 믿습니다.)

은 무엇 당신이 할 수있는 것은 shared_ptr의 수에의 포인터 타입을 정의하는 것입니다 (부스트 또는 표준 중 하나 중요하지 않습니다). 이런 식으로 뭔가 :

void passNewAToPython() 
{ 
    A * a = make_shared<A>(); 
    PyGILState_STATE _GILState = PyGILState_Ensure();  
    //Should really use a try catch here too but lets ignore that for now 
    boost::python::call_method<void>(pythonCallbacks, "newA", a); 
    PyGILState_Release(_GILState); 
} 
관련 문제