如何使用 Python 的 cffi 和枚举数组
How to work with Python's cffi and enum arrays
我有一个用 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 *
...
时我必须缺少一些东西
您必须使用 _adsl
模块中的 ffi 对象:
from _asdf import ffi
而不是创建一个新的 FFI 实例并重新定义一个恰好相同的不相关类型 enum translation
。
我有一个用 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 *
...
您必须使用 _adsl
模块中的 ffi 对象:
from _asdf import ffi
而不是创建一个新的 FFI 实例并重新定义一个恰好相同的不相关类型 enum translation
。