所以我不完全確定如何問這個問題,因爲我與另一個人的代碼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()
'my_callback'需要是可以調用'self.handler',所以記住這是在討論的版本的方法。取而代之的是將實例'__init__'設置爲'self._callback = MTContactCallbackFunction(self.my_callback)',它使用Python引用保持回調實例的活性。然後更改註冊以使用'self.MTRegisterContactFrameCallback(device,self._callback)'。 – eryksun
順便說一句,爲每個實例提交共享庫refcount(即爲其加載'CDLL')是浪費時間,正如定義'__init__'中的所有函數原型一樣,所以您可以提供一個版本,將這些定義移動到如果不是模塊級別,則至少達到課程級別。 – eryksun
@eryksun你的方法解決了這個問題。我現在要清理其他程序的速度,因爲我有一個工作模型。謝謝! –