Как работать с массивами cffi и enum в Python - PullRequest
0 голосов
/ 26 октября 2018

У меня есть функция, реализованная в C, которая переводит строку в массив определенного enum.Код C выглядит следующим образом:

Заголовочный файл (описывает enum):

/* File `asdf.h` */
enum translation {
        ONE,
        ANOTHER,
        FINISH,
};

void translate(char *origin, enum translation *destination);

Исходный файл (реализует функцию, которая выполняет перевод):

/* File `asdf.c` */
#include "asdf.h"


void translate(char *origin, enum translation *destination)
{
    while (1) {
        if (*origin == 'F')
            break;
        if (*origin == 'O')
            *destination++ = ONE;
        if (*origin == 'A')
            *destination++ = ANOTHER;
        origin++;
    }
    *destination = FINISH;
}

Теперь я хотел бы иметь возможность вызывать эту функцию из Python, используя CFFI , и иметь возможность проверять правильные значения выходного массива (перевод).Как я мог это сделать?

Я попытался сначала скомпилировать модуль, а затем создать переменные и вызвать функцию таким образом, но не смог заставить его работать:

# File `cffienum.py`
from pathlib import Path
from cffi import FFI


ffibuilder = FFI()
ffibuilder.cdef(Path('asdf.h').read_text())
ffibuilder.set_source(
    '_asdf',  # name of the output C extension
    '#include "asdf.h"',
    sources=['asdf.c'])   # includes asdf.c as additional sources
ffibuilder.compile()


if __name__ == '__main__':
    from _asdf.lib import translate

    ffi = FFI()
    ffi.cdef(Path('asdf.h').read_text())
    c = ffi.dlopen('c')
    source = ffi.new('char source[]', b'OAF')
    destination = ffi.new('enum translation destination[10]')

    translate(source, destination)
    print(source, destination)

Это ошибка, которую я получаю:

$ pipenv run python cffienum.py 
Traceback (most recent call last):
  File "cffienum.py", line 24, in <module>
    translate(source, destination)
TypeError: initializer for ctype 'enum translation *' must be a pointer to same type, not cdata 'enum translation[10]'

Первый контакт с CFFI, а не с опытным программистом C, так что держу пари, что я здесь много чего неправильно делаю.

Обновление

Обратите внимание, что если вместо:

void translate(char *origin, enum translation *destination)

я использую:

void translate(char *origin, char *destination)

Или:

void translate(char *origin, uint8_t *destination)

Работает просто отлично.Так что я должен что-то упустить при использовании enum translation * ...

1 Ответ

0 голосов
/ 27 октября 2018

Вы должны использовать объект ffi из модуля _adsl:

from _asdf import ffi

вместо создания нового экземпляра FFI и переопределения несвязанного типа enum translation, который оказывается идентичным.

...