2013-09-28 2 views
1

J'écris une application Python qui utilise l'API PulseAudio. L'implémentation utilise beaucoup les callbacks écrits en Python et invoqués par le code C de PulseAudio.Convertir un tableau de pointeurs en tableau de structures Python

Les informations les plus est passé dans le rappel par une structure spécifique, par exemple pa_sink_info, qui est defined en C comme suit:

typedef struct pa_sink_info { 
    const char *name;     
    uint32_t index;      
    const char *description;   
    pa_sample_spec sample_spec;   
    pa_channel_map channel_map;   
    uint32_t owner_module;    
    pa_cvolume volume;     
    int mute;       
    uint32_t monitor_source;   
    const char *monitor_source_name; 
    pa_usec_t latency;     
    const char *driver;     
    pa_sink_flags_t flags;    
    pa_proplist *proplist;    
    pa_usec_t configured_latency;  
    pa_volume_t base_volume;   
    pa_sink_state_t state;    
    uint32_t n_volume_steps;   
    uint32_t card;      
    uint32_t n_ports;     
    pa_sink_port_info** ports;   
    pa_sink_port_info* active_port;  
    uint8_t n_formats;     
    pa_format_info **formats;   
} pa_sink_info; 

De cette structure, il est très facile d'obtenir des valeurs scalaires, par exemple .:

self.some_proc(
    struct.contents.index, 
    struct.contents.name, 
    struct.contents.description) 

Mais j'ai une difficulté à faire face à ports et active_port, qui en Python sont décrits comme:

('n_ports', uint32_t), 
('ports', POINTER(POINTER(pa_sink_port_info))), 
('active_port', POINTER(pa_sink_port_info)), 

Ici n_ports spécifie nombre d'éléments ports, qui est un pointeur sur un tableau de pointeurs vers des structures de type pa_sink_port_info. En fait, je ne sais même pas comment je peux les convertir en types Python.

Quel est le moyen le plus efficace de convertir ports en Python dictionnaire contenant pa_sink_port_info?

Répondre

0

La résolution de ce problème nécessitait une lecture attentive de ctypes reference de Python. Une fois le mécanisme de mise en œuvre de traduction de type ctypes était clair, il n'est pas si difficile d'obtenir les valeurs souhaitées.

L'idée principale à propos des pointeurs est que vous utilisez leur attribut contents pour accéder aux données pointées par le pointeur. Une autre chose utile à savoir est que les pointeurs peuvent être indexés comme des tableaux (ils ne sont pas validés par l'interpréteur, donc il est de votre responsabilité de vous assurer qu'il s'agit bien d'un tableau).

Pour cet exemple particulier PulseAudio, nous pouvons traiter les membres de la structure ports (qui est un pointeur sur un tableau de pointeurs) comme suit:

port_list = [] 
if struct.contents.ports: 
    i = 0 
    while True: 
    port_ptr = struct.contents.ports[i] 
    # NULL pointer terminates the array 
    if port_ptr: 
     port_struct = port_ptr.contents 
     port_list.append(port_struct.name) 
     i += 1 
    else: 
     break 
Questions connexes