2009-09-29 20 views

Respuesta

6

Desde OS X 10.5, OS X se ha incluido con el puente PyObjC, un puente Python-Objective-C. Utiliza el marco BridgeSupport para mapear frameworks Objective-C a Python. A diferencia, MacRuby, PyObjC es un puente clásico: hay un objeto proxy en el lado python para cada objeto ObjC y viceversa. Sin embargo, el puente es bastante fluido y es posible escribir aplicaciones completas en PyObjC (Xcode tiene soporte básico de PyObjC, y puedes descargar la aplicación y las plantillas de archivos para Xcode desde el SVN de PyObjC en el enlace de arriba). Mucha gente lo usa para utilidades o para aplicaciones/scripts/complementos. El sitio para desarrolladores de Apple también tiene un introduction para desarrollar aplicaciones Cocoa con Python a través de PyObjC, que está un poco desactualizado, pero puede ser una buena visión general para usted.

En su caso, el siguiente código llamará [NSSpeechSynthesizer availableVoices]:

from AppKit import NSSpeechSynthesizer 

NSSpeechSynthesizer.availableVoices() 

que devuelve

(
    "com.apple.speech.synthesis.voice.Agnes", 
    "com.apple.speech.synthesis.voice.Albert", 
    "com.apple.speech.synthesis.voice.Alex", 
    "com.apple.speech.synthesis.voice.BadNews", 
    "com.apple.speech.synthesis.voice.Bahh", 
    "com.apple.speech.synthesis.voice.Bells", 
    "com.apple.speech.synthesis.voice.Boing", 
    "com.apple.speech.synthesis.voice.Bruce", 
    "com.apple.speech.synthesis.voice.Bubbles", 
    "com.apple.speech.synthesis.voice.Cellos", 
    "com.apple.speech.synthesis.voice.Deranged", 
    "com.apple.speech.synthesis.voice.Fred", 
    "com.apple.speech.synthesis.voice.GoodNews", 
    "com.apple.speech.synthesis.voice.Hysterical", 
    "com.apple.speech.synthesis.voice.Junior", 
    "com.apple.speech.synthesis.voice.Kathy", 
    "com.apple.speech.synthesis.voice.Organ", 
    "com.apple.speech.synthesis.voice.Princess", 
    "com.apple.speech.synthesis.voice.Ralph", 
    "com.apple.speech.synthesis.voice.Trinoids", 
    "com.apple.speech.synthesis.voice.Vicki", 
    "com.apple.speech.synthesis.voice.Victoria", 
    "com.apple.speech.synthesis.voice.Whisper", 
    "com.apple.speech.synthesis.voice.Zarvox" 
) 

(NSCFArray un puente) en mi máquina SL.

3

Probablemente desee PyObjC. Dicho esto, nunca lo he usado (solo he visto demos), así que no estoy seguro de que haga lo que necesita.

4

Mac OS X de 10.5 en adelante se incluye con Python y el módulo objc que le permitirá hacer lo que desee.

Un ejemplo:

from Foundation import * 

thing = NSKeyedUnarchiver.unarchiveObjectWithFile_(some_plist_file) 

Puede encontrar más documentación here.

+0

+1 por ejemplo. –

+1

No necesita importar el módulo objc, solo Foundation. –

+0

Hah, tienes razón. Actualizaré mi ejemplo. – Benno

19

Como han mencionado otros, PyObjC es el camino a seguir. Pero, por el amor integridad, aquí es cómo puede hacerlo con ctypes, en caso de que lo necesite para trabajar en las versiones de OS X anteriores a 10.5 que no tienen PyObjC instalados:

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')) 

No es bastante , pero hace el trabajo. La lista final de nombres disponibles se almacena en la variable voiceNames anterior.

2012-4-28 Actualización: Solucionado para trabajar en compilaciones de Python de 64 bits, asegurándose de que todos los parámetros y tipos de retorno se pasan como punteros en lugar de enteros de 32 bits.

+0

Hola, esto falla en 10.6 - ¿Alguna idea de por qué? –

+3

@Ecir: Gracias por el consejo, me sorprende que el código original funcionó en primer lugar. El problema era que todos los punteros (punteros de clase y punteros de instancia) se truncaban a 32 bits debido a la forma en que funcionaban los tipos, lo que provocaba bloqueos. Para solucionarlo, cambié el código para establecer todos los tipos de resultados y tipos de argumentos para que sean punteros explícitamente. –

+0

Gracias, funciona ahora. –

Cuestiones relacionadas