2009-11-10 5 views
1

EDIT: En relisant ma question initiale, j'ai réalisé très rapidement que c'était très mal formulé, ambigu, et trop confus pour obtenir une réponse décente. C'est ce que je reçois pour répondre à une question à la fin de ma pause déjeuner. J'espère que cela sera plus clair:Création d'un PyBuffer à partir d'un struct struct

J'essaie d'exposer une structure C simple à Python (3.x) en tant que PyBuffer afin que je puisse en récupérer une MemoryView. La structure que je veux exposer est semblable à ceci:

struct ImageBuffer { 
    void* bytes; 
    int row_count; 
    int bytes_per_row; 
}; 

et il est mon désir de permettre à l'auteur de script pour accéder aux données comme ceci:

img_buffer = img.get_buffer() 
img_buffer[1::4] = 255 # Set every Red component to full intensity 

Malheureusement la documentation existante sur l'API C car ces structures sont plutôt clairsemées, auto-contradictoires par endroits et carrément erronées chez les autres (les signatures documentées des fonctions ne correspondent pas à celles des en-têtes, etc.). Je n'ai donc pas une très bonne idée de la meilleure façon de l'exposer. Aussi, je voudrais éviter d'inclure des librairies tierces pour réaliser des fonctionnalités qui devraient faire partie des librairies principales, mais il me semble que la fonctionnalité PyBuffer est encore assez immature, et peut-être que quelque chose comme NumPy serait un meilleur choix.

Quelqu'un a-t-il un conseil à ce sujet?

Répondre

1

L'ensemble des méthodes pour mettre en œuvre afin que votre type d'extension prend en charge le protocole tampon est décrit ici: http://docs.python.org/3.1/c-api/typeobj.html#buffer-object-structures

Je reconnais que la documentation est assez rude, donc le meilleur conseil que je puisse donner est de commencer à partir d'un existant implémentation de l'API buffer par un type C, par exemple bytesobject.c ou bytearrayobject.c dans le code source officiel de Python.

Cependant, veuillez noter que le protocole de buffer ne donne pas accès à des notations de haut niveau comme celle que vous avez citée: img_buffer[1::4] = 255 ne fonctionnera pas sur un objet memoryview.

Édition: Pour être plus précis, les memoryviews prennent en charge certains types d'attribution de tranches, mais pas toutes. En outre, ils ne sont pas assez "intelligents" pour comprendre qu'assigner 255 à une tranche signifie en fait que vous voulez que la valeur de l'octet soit répétée. Exemple:

 
>>> b = bytearray(b"abcd") 
>>> m = memoryview(b) 
>>> m[0:2] = b"xy" 
>>> b 
bytearray(b'xycd') 
>>> m[0:2] = 255 
Traceback (most recent call last): 
    File "", line 1, in 
TypeError: 'int' does not support the buffer interface 
>>> m[0:2] = b"x" 
Traceback (most recent call last): 
    File "", line 1, in 
ValueError: cannot modify size of memoryview object 
>>> m[0::2] = b"xy" 
Traceback (most recent call last): 
    File "", line 1, in 
NotImplementedError 
+0

Vraiment? Les visions de mémoire ne coupent pas? Je pensais que c'était censé être le grand avantage de les utiliser. Est-ce qu'ils supportent au moins l'indexation de base? Le but de ma tentative d'exposer cette mémoire est de permettre aux développeurs Python de manipuler des données d'image au niveau octet, et s'ils ne peuvent pas faire d'indexation ou de découpage de base, cette méthode est inutile pour moi. – Toji

+0

Voir la version éditée ci-dessus. –

+0

Ah, merci pour la clarification. C'est plus conforme à ce que je pensais. Je vais devoir jouer avec ça et voir si je peux trouver un bon moyen de réaliser ce que je veux. Merci encore! – Toji