2011-09-12 1 views
2

私はPyObjCを使用しています。 PyObjCはmethod_exchangeImplementationsへのインターフェイスを提供していないので、私はctypes経由でこの関数を使用しようとしていました。私はいくつかのウィンドウコントローラクラスからwindowShouldClose:を上書きしようとしていました。PyObjCおよびmethod_exchangeImplementations:クラッシュ正しい使用法?

マイコード:

import objc 
BrowserWindowController = objc.lookUpClass("BrowserWindowController") 

class BrowserWindowController(objc.Category(BrowserWindowController)): 
    def myWindowShouldClose_(self, sender): 
     print "myWindowShouldClose", self, sender 
     return self.myWindowShouldClose_(sender) 

from ctypes import * 
capi = pythonapi 

# id objc_getClass(const char *name) 
capi.objc_getClass.restype = c_void_p 
capi.objc_getClass.argtypes = [c_char_p] 

# SEL sel_registerName(const char *str) 
capi.sel_registerName.restype = c_void_p 
capi.sel_registerName.argtypes = [c_char_p] 

def capi_get_selector(name): 
    return c_void_p(capi.sel_registerName(name)) 

# Method class_getInstanceMethod(Class aClass, SEL aSelector) 
# Will also search superclass for implementations. 
capi.class_getInstanceMethod.restype = c_void_p 
capi.class_getInstanceMethod.argtypes = [c_void_p, c_void_p] 

# void method_exchangeImplementations(Method m1, Method m2) 
capi.method_exchangeImplementations.restype = None 
capi.method_exchangeImplementations.argtypes = [c_void_p, c_void_p] 

def hook_into_close(): 
    clazz = capi.objc_getClass("BrowserWindowController") 
    origClose = capi.class_getInstanceMethod(clazz, capi_get_selector("windowShouldClose:")) 
    newClose = capi.class_getInstanceMethod(clazz, capi_get_selector("myWindowShouldClose:")) 
    capi.method_exchangeImplementations(origClose, newClose) 

これがクラッシュします。奇妙なバックトレースは[NSWindow _close]です。

コードは基本的に正しいですか?

何が問題ですか?

+0

BrowserWindowControllerはあなたのクラスですか?もしそうなら、なぜ自分の実装で何をする必要があるのではなく、別のものの実装を交換していますか? –

+0

@Peter:いいえ、実装を変更できない別のフレームワークからのものです。 – Albert

答えて

1

ああ、@objc.signature(BrowserWindowController.windowWillClose_.signature)の前にdef myWindowShouldClose_を追加すると、それ以上クラッシュしません。

それでは、間違った/一致しない署名がありました。

関連する問題