2012-09-18 114 views
4

我有興趣在python中使用C++類。看着Calling C/C++ from python?,我決定嘗試ctypes。但是,當我嘗試更改類成員的值時,會出現段錯誤。ctypes類成員訪問segfaulting

下面是一個簡單的例子,重現我的問題:

的C/C++側:

#include <iostream> 

class Foo{ 
    private: 
     int mValue; 
    public: 
     void bar(){ 
      std::cout << "Hello" << std::endl; 
     } 
     void setValue(int inValue) { 
      mValue = inValue; 
      std::cout << "Value is now: " << mValue << std::endl; 
     } 
     void setValue2() { 
      mValue = 2; 
      std::cout << "Value is now: " << mValue << std::endl; 
     } 
}; 

extern "C" { 
    Foo* Foo_new(){ return new Foo(); } 
    void Foo_bar(Foo* foo){ foo->bar(); } 
    void Foo_setValue(Foo* foo, int v) { foo->setValue(v); } 
    void Foo_setValue2(Foo* foo) { foo->setValue2(); } 
} 

的代碼是在OSX上編譯:

g++ -c -fPIC foo.cpp -o foo.o && g++ -shared -Wl -o libfoo.dylib foo.o 

Python端:

from ctypes import * 
lib = cdll.LoadLibrary('./libfoo.dylib') 

class Foo(object): 
    def __init__(self): 
     self.obj = lib.Foo_new() 
    def bar(self): 
     lib.Foo_bar(self.obj) 
    def set(self, v): 
     lib.Foo_setValue(self.obj, v); 
    def set2(self): 
     lib.Foo_setValue2(self.obj); 

我可以打電話給酒吧,但是如果我打電話給set或set2,我會遇到段錯誤。

f = Foo() 
f.bar() # Ok 
f.set(3) # Segfault 

很明顯,我錯過了一些東西。

+0

它適用於我 –

+0

具體而言,我使用鏈接後的確切編譯參數:'g ++ -c -fPIC foo.cpp -o foo.o'和'g ++ -shared -Wl,-soname,libfoo.so -o libfoo.so foo.o',然後加載'./ libfoo.so' –

+0

剛剛在Linux上試過,正如你所說的那樣。但是,在OSX 10.7.4和10.6.8上,我收到段錯誤。似乎是一個特定於平臺的問題。 – jfdupuis

回答

1

使用下面的解決了這個問題:

def __init__(self): 
    lib.Foo_new.restype = c_void_p # Needed 
    self.obj = lib.Foo_new() 

def set(self, v): 
    lib.Foo_setValue(c_void_p(self.obj), v) # c_void_p needed 

閱讀周圍,這似乎是一個64位指針的問題。

+0

您也可以使用'lib.Foo_setValue.argtypes = [c_void_p,c_int]'來聲明參數類型。然後,每次使用它時都不必包裝參數。 –