Criando um PyBuffer de um struct C
-
19-09-2019 - |
Pergunta
EDIT: Após a re-ler a minha pergunta original percebi muito rapidamente que foi muito mal formulada, ambíguo, e muito confuso para nunca obter uma resposta decente. Isso é o que eu ganho por correndo para fora uma pergunta no final do meu horário de almoço. Esperemos que este será mais claro:
Eu estou tentando expor uma estrutura C simples para Python (3.x) como um PyBuffer para que eu possa recuperar um MemoryView dele. A estrutura eu quero expor é semelhante a este:
struct ImageBuffer {
void* bytes;
int row_count;
int bytes_per_row;
};
e é meu desejo para permitir que o roteirista para acessar os dados da seguinte forma:
img_buffer = img.get_buffer()
img_buffer[1::4] = 255 # Set every Red component to full intensity
Infelizmente a documentação existente sobre a API C para estas estruturas é bastante escassa, auto contraditória em alguns lugares, e outright errado em outros (assinaturas de função documentados não coincidem com aqueles nos cabeçalhos, etc.) como tal não tenho uma idéia muito boa sobre a melhor forma de expor isso. Além disso, eu gostaria de evitar incluindo libs de terceiros para alcançar a funcionalidade que deve ser parte das libs do núcleo, mas parece-me que a funcionalidade PyBuffer ainda é bastante imaturo, e talvez algo como NumPy seria uma escolha melhor.
Alguém tem algum conselho sobre isso?
Solução
O conjunto de métodos para implementar de modo a que o seu tipo de extensão suporta o protocolo buffer é descrito aqui: http://docs.python.org/3.1/c-api/typeobj.html#buffer-object-structures
Eu reconheço que a documentação é muito difícil, então o melhor conselho que posso dar é para começar a partir de uma implementação existente da API tampão por um tipo C, por exemplo bytesobject.c ou bytearrayobject.c no código oficial fonte Python .
No entanto, note que o protocolo tampão não dá acesso a notações de alto nível, como o que você citou:. img_buffer[1::4] = 255
não vai funcionar em um objeto memoryview
Editar: para ser mais preciso, memoryviews suportar alguns tipos de atribuição fatia, mas não todos eles. Além disso, eles não são "inteligentes" o suficiente para entender que a atribuição de 255 para uma fatia na verdade significa que você deseja que o valor de byte a ser repetido. Exemplo:
>>> 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