2015-10-18 25 views
1

所以我不完全確定如何問這個問題,因爲我與另一個人的代碼http://pb.lericson.se/p/FpbYhX/使用ctypes的部分進行交互,我找不到任何其他答案,這是關閉: How can I get methods to work as callbacks with python ctypes?)。無論如何,這裏就是這樣。pytyt內部ctypes的實例方法

所以我想運行的QThread類中,上面的代碼,所以我可以與相關的信息傳遞pyqtSignal回到我的主程序,但我無法弄清楚如何克服以下錯誤:

ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: expected CFunctionType instance instead of instance method 

我只是真的知道python,並且在剛纔之前還沒有與cTypes交互過。下面是這個代碼繪製的更廣泛的類(這基本上就是我將大部分代碼從鏈接文件複製到QThread類中)。問題發生在底部17行。據我所知,python在「self.MTRegisterContactFrameCallback」中使用「self.my_callback」對我不滿意,因爲my_callback是一個實例方法。這一切都很好,但是如何讓這個實例方法變爲CFunctionType,同時仍然保留在我的類中?

class Handler(QThread): 
    trackPadTouched = pyqtSignal(str) 
    def __init__(self, parent=None): 
    super(Handler, self).__init__(parent) 
    self.parent = parent 
    print self.parent 
    global MTFunctions 
    MTFunctions = MTFunctions(parent=self) 
    self.parent = parent 
    CFArrayRef = ctypes.c_void_p 
    CFMutableArrayRef = ctypes.c_void_p 
    CFIndex = ctypes.c_long 

    self.MultitouchSupport =  ctypes.CDLL("/System/Library/PrivateFrameworks/MultitouchSupport.framework/MultitouchSupport") 

    self.CFArrayGetCount = self.MultitouchSupport.CFArrayGetCount 
    self.CFArrayGetCount.argtypes = [CFArrayRef] 
    self.CFArrayGetCount.restype = CFIndex 

    self.CFArrayGetValueAtIndex = self.MultitouchSupport.CFArrayGetValueAtIndex 
    self.CFArrayGetValueAtIndex.argtypes = [CFArrayRef, CFIndex] 
    self.CFArrayGetValueAtIndex.restype = ctypes.c_void_p 

    MTDeviceCreateList = self.MultitouchSupport.MTDeviceCreateList 
    MTDeviceCreateList.argtypes = [] 
    MTDeviceCreateList.restype = CFMutableArrayRef 
    MTDataRef = ctypes.POINTER(MTData) 



    MTDeviceRef = ctypes.c_void_p 

    self.MTRegisterContactFrameCallback = self.MultitouchSupport.MTRegisterContactFrameCallback 
    self.MTRegisterContactFrameCallback.argtypes = [MTDeviceRef, ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, MTDataRef, ctypes.c_int, ctypes.c_double, ctypes.c_int)] 
    self.MTRegisterContactFrameCallback.restype = None 

    MTDeviceStart = self.MultitouchSupport.MTDeviceStart 
    MTDeviceStart.argtypes = [MTDeviceRef, ctypes.c_int] 
    MTDeviceStart.restype = None 


    devices = self.MultitouchSupport.MTDeviceCreateList() 
    num_devices = self.CFArrayGetCount(devices) 
    print "num_devices =", num_devices 
    for i in xrange(num_devices): 
     device = self.CFArrayGetValueAtIndex(devices, i) 
     print "device #%d: %016x" % (i, device) 
     self.MTRegisterContactFrameCallback(device, self.my_callback) 
     self.MTDeviceStart(device, 0) 

    def my_callback(self, device, data_ptr, n_fingers, timestamp, frame): 
    #print threading.current_thread(), device, data_ptr, n_fingers, timestamp, frame 
    for i in xrange(n_fingers): 
     data = data_ptr[i] 
     d = [data_ptr[i].normalized.position.x * 100, data_ptr[i].normalized.position.y * 100] 
     self.handler(i, d, n_fingers) 
    return 0 

def main(): 
    app = QtGui.QApplication(sys.argv) 
    ex = Handler() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

回答

0

完全未經測試,但試試這個:

MTContactCallbackFunction = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, 
           MTDataRef, ctypes.c_int, 
           ctypes.c_double, ctypes.c_int) 

class Handler(QThread): 
    trackPadTouched = pyqtSignal(str) 
    def __init__(self, parent=None): 
    ... 
    self.MTRegisterContactFrameCallback.argtypes = [MTDeviceRef, MTContactCallbackFunction] 
    ... 

    @MTContactCallbackFunction 
    def my_callback(device, data_ptr, n_fingers, timestamp, frame): 
    ... 
+0

'my_callback'需要是可以調用'self.handler',所以記住這是在討論的版本的方法。取而代之的是將實例'__init__'設置爲'self._callback = MTContactCallbackFunction(self.my_callback)',它使用Python引用保持回調實例的活性。然後更改註冊以使用'self.MTRegisterContactFrameCallback(device,self._callback)'。 – eryksun

+0

順便說一句,爲每個實例提交共享庫refcount(即爲其加載'CDLL')是浪費時間,正如定義'__init__'中的所有函數原型一樣,所以您可以提供一個版本,將這些定義移動到如果不是模塊級別,則至少達到課程級別。 – eryksun

+0

@eryksun你的方法解決了這個問題。我現在要清理其他程序的速度,因爲我有一個工作模型。謝謝! –