重命名/重新声明 CFFI 函数?

问题描述 投票:0回答:1

我有一个 C 库,我正在尝试为其创建(外线,API 模式)CFFI 绑定。 C 库提供了每个函数的各种实现,但它们都添加了这个巨大的、令人讨厌的前缀。

例如,GreenSpam子模块中的foo函数的AVX优化实现被命名为

THELIBRARY_GREENSPAM_OPTIMIZED_AVX_foo()
;我会将其公开为
TheLibrary.Spam.GreenSpam.foo
,并在 import 时间选择
透明
的 CPU 优化。

am能够在

ffibuilder.compile()
时间为每个模块确定这个前缀,所以我想尝试尽可能地倾向于DRY。我的代码目前看起来像这样,正如您所看到的,就 DRY 而言,这几乎是可怕的 并且 没有提供任何简单或明显的途径来在运行时算法选择上前进:

# TheLibrary/Spam/GreenSpam.py
from . import _greenspam_generic
from . import _greenspam_optimized_avx  # TODO

__all__ = ['foo', 'oof']

def foo(bar):
    """GreenSpam foo"""
    _out = _greenspam_generic.ffi.new(f"uint8_t[{len(bar):d}]")
    _greenspam_generic.lib.THELIBRARY_GREENSPAM_GENERIC_foo(bar, len(bar), _out)
    # void function never errors
    return bytes(_out)

def oof(baz):
    """GreenSpam oof"""
    _out = _greenspam_generic.ffi.new(f"uint8_t[{len(baz):d}]")
    err = _greenspam_generic.lib.THELIBRARY_GREENSPAM_GENERIC_oof(baz, len(baz), _out)
    if err:
        raise RuntimeError("oof")
    return bytes(_out)
# TheLibrary/Spam/PurpleSpam.py
from . import _purplespam_generic
from . import _purplespam_optimized_avx  # TODO

__all__ = ['foo', 'oof']

def foo(bar):
    """PurpleSpam foo"""
    _out = _purplespam_generic.ffi.new(f"uint8_t[{len(bar):d}]")
    _purplespam_generic.lib.THELIBRARY_PURPLESPAM_GENERIC_foo(bar, len(bar), _out)
    # void function never errors
    return bytes(_out)

def oof(baz):
    """PurpleSpam oof"""
    _out = _purplespam_generic.ffi.new(f"uint8_t[{len(baz):d}]")
    err = _purplespam_generic.lib.THELIBRARY_PURPLESPAM_GENERIC_oof(baz, len(baz), _out)
    if err:
        raise RuntimeError("oof")
    return bytes(_out)

我真的很想在运行

ffi.compile()
时展平这些 C 库函数名称,理想情况下公开诸如
(fr'\b{re.escape(prefix)}_(\w+)\b', r'\1')
之类的别名,以使我的 bindings' 代码更清晰、更好,特别是使我能够添加在这些导入时 CPU 选择中,无需再次重复我的代码。 我想尽可能密切地跟踪上游库,因此对 C 源代码进行转换以删除这些前缀会很痛苦,我想特别询问

替代方案

这样做。 但是,我可以很好地添加,例如在

ffibuilder.set_source()

期间,将规范化的

aliases
添加到损坏的名称中,特别是如果可以以专注于DRY的方式完成的话。 (我确实尝试过函数引用,但显然那些只是C++?)

我目前正在查看的特定库是
PQClean

,但我预计我也会在未来的绑定中遇到这个问题,所以这是反对过度深入转换 C 源代码的另一点,因为我会每次我遇到一个新库时都必须重新重复这项工作,并且可能每次该库重构其标头意大利面时都必须重复该工作。

python namespaces function-declaration python-cffi
1个回答
0
投票

# to make the builds "mylib_<suffix>.so" for suffix in ['generic', 'optimized_avx']: builder = FFIBuilder() builder.set_source("mylib_" + suffix, f""" #include <mylib.h> int foo_{suffix}(int x, int y); void bar_{suffix}(void); """) builder.compile() # minimal source code for mylib_generic.py import _mylib_maker globals().update(_mylib_maker.make("generic")) # minimal source code for mylib_optimized_avx.py import _mylib_maker globals().update(_mylib_maker.make("optimized_avx")) # actual Python-side wrappers defined in _mylib_maker.py def make(suffix): mod = __import__("mylib_" + suffix) c_foo = getattr(mod, "foo_" + suffix) c_bar = getattr(mod, "bar_" + suffix) my_funcs = [] @my_funcs.append def foo(x, y): result = c_foo(x, y) if result < 0: raise Exception return result @my_funcs.append def bar(): return c_bar() return {func.__name__: func for func in my_funcs}

© www.soinside.com 2019 - 2024. All rights reserved.