calling Objective C functions from Python?

前端 未结 4 1731
刺人心
刺人心 2020-12-14 04:19

Is there a way to dynamically call an Objective C function from Python?

For example, On the mac I would like to call this Objective C function

[NSSpe         


        
4条回答
  •  忘掉有多难
    2020-12-14 05:17

    As others have mentioned, PyObjC is the way to go. But, for completeness' sake, here's how you can do it with ctypes, in case you need it to work on versions of OS X prior to 10.5 that do not have PyObjC installed:

    import ctypes
    import ctypes.util
    
    # Need to do this to load the NSSpeechSynthesizer class, which is in AppKit.framework
    appkit = ctypes.cdll.LoadLibrary(ctypes.util.find_library('AppKit'))
    objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))
    
    objc.objc_getClass.restype = ctypes.c_void_p
    objc.sel_registerName.restype = ctypes.c_void_p
    objc.objc_msgSend.restype = ctypes.c_void_p
    objc.objc_msgSend.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    
    # Without this, it will still work, but it'll leak memory
    NSAutoreleasePool = objc.objc_getClass('NSAutoreleasePool')
    pool = objc.objc_msgSend(NSAutoreleasePool, objc.sel_registerName('alloc'))
    pool = objc.objc_msgSend(pool, objc.sel_registerName('init'))
    
    NSSpeechSynthesizer = objc.objc_getClass('NSSpeechSynthesizer')
    availableVoices = objc.objc_msgSend(NSSpeechSynthesizer, objc.sel_registerName('availableVoices'))
    
    count = objc.objc_msgSend(availableVoices, objc.sel_registerName('count'))
    voiceNames = [
      ctypes.string_at(
        objc.objc_msgSend(
          objc.objc_msgSend(availableVoices, objc.sel_registerName('objectAtIndex:'), i),
          objc.sel_registerName('UTF8String')))
      for i in range(count)]
    print voiceNames
    
    objc.objc_msgSend(pool, objc.sel_registerName('release'))
    

    It ain't pretty, but it gets the job done. The final list of available names is stored in the voiceNames variable above.

    2012-4-28 Update: Fixed to work in 64-bit Python builds by making sure all parameters and return types are passed as pointers instead of 32-bit integers.

提交回复
热议问题