2012-12-06 3 views
2

나는 python ctypes 모듈을 낯선 사람은 아니지만 이것은 C++, C 및 Python을 모두 하나의 코드로 결합한 첫 번째 시도입니다. 내 문제는 Seg fault when using ctypes with Python and C++과 매우 유사하지만 문제를 같은 방법으로 해결할 수는 없습니다. ctypes/C++ segfault 액세스 멤버 변수

나는 간단한 C++ 파일 Header.cpp라고 있습니다

g++ -c Header.cpp -fPIC -o Header.o 
g++ -shared -fPIC -o libHeader.so Header.o 

test.py라는 간단한 파이썬 래퍼 :

import ctypes as C 
lib = C.CDLL('./libHeader.so') 

class Foo(object): 
    def __init__(self,nbits): 
     self.nbits = C.c_int(nbits) 
     self.obj = lib.Foo_new(self.nbits) 

    def bar(self): 
     lib.Foo_bar(self.obj) 

def main(): 
    f = Foo(32) 
    f.bar() 

if __name__ == "__main__": 
    main() 
을 내가 사용하여 공유 라이브러리에 컴파일

#include <iostream> 

class Foo{ 
    public: 
     int nbits; 
     Foo(int nb){nbits = nb;} 
     void bar(){ std::cout << nbits << std::endl; } 
}; 

extern "C" { 
    Foo *Foo_new(int nbits){ return new Foo(nbits); } 
    void Foo_bar(Foo *foo){ foo->bar(); } 
} 

나는 test.py를 호출 할 때 numbe를 가져야한다고 생각한다. r 32가 화면에 인쇄됩니다. 그러나, 내가 얻는 것은 모두 세분화 오류입니다. 스택에서 클래스 인스턴스를 반환하도록 생성자를 변경 한 다음 (예 : new 호출없이) 객체를 전달하면 프로그램이 예상대로 수행됩니다. 또한,의 방법을 변경하여 nbits 멤버를 사용하지 않는 경우, 프로그램에서 오류가 발생하지 않습니다.

저는 C++에 대한 제한된 이해가 있습니다. 그러나 C 및 C++에서이 함수를 예상대로 사용할 수 있지만 Python에서는 사용할 수 없다는 사실은 다소 혼란 스럽습니다. 어떤 도움이라도 대단히 감사하겠습니다.

업데이트 : 아래 의견 중 하나 덕분에 문제가 해결되었습니다. 이 경우 C 함수에 대한 restype 및 argtypes에 대한 명시적인 선언이 필요했습니다.

lib.Foo_new.restype = C.c_void_p; 
lib.Foo_new.argtypes = [C.c_int32]; 
lib.Foo_bar.restype = None; 
lib.Foo_bar.argtypes = [C.c_void_p]; 
+0

저에게 맞습니다. Erratum : Header.cpp를 -fPIC 스위치로 컴파일했다고 가정합니다. – udoprog

+0

여기에서도 작동합니다. segfault의 gdb 백 트레이스를 제공하십시오. –

+3

나를 위해 일한다. Foo에 대한 포인터를 C int로 전달하면 실패 할 수 있습니다. argtypes 및 restype 함수를 지정해보십시오. 'lib.Foo_new.restype = C.c_void_p; lib.Foo_new.argtypes = [C.c_int32]; lib.Foo_bar.restype = None; lib.Foo_bar.argtypes = [C.c_void_p]' – cgohlke

답변

0

내가 다음을 시도합니다 : : 다음 코드에 추가되었습니다 즉

extern "C" 
{ 
    Foo *Foo_new(int nbits) 
    { 
     Foo *foo = new Foo(nbits); 
     printf("Foo_new(%d) => foo=%p\n", nbits, foo); 
     return foo; 
    } 
    void Foo_bar(Foo *foo) 
    { 
     printf("Foo_bar => foo=%p\n", foo); 
     foo->bar(); 
    } 
} 

보고하는 경우 foo의 값이 일치.

또한 Boost.Python을보고 C++ 객체의 Python 바인딩을 쉽게 작성할 수 있습니다.

+0

이 경우 래핑 될 코드의 양은 매우 적습니다. 따라서 Boost.Python을 사용하면 과도하게 불필요한 종속성이 추가 될 것입니다. – ebarr