cffi easytier-ffi python 集成试用

主要是一个简单测试,学习下cffi 集成c library

参考玩法

  • 项目结构
├── api_build.py // 生成代码
├── app.py // 测试
├── app.yaml // 测试配置
├── easytier // 模块
│   ├── __init__.py
│   ├── easytier_cffi.py // 生成的代码
│   └── lib
│       └── libeasytier_ffi.dylib // 依赖库,当前是macos 的
├── easytier.h
├── LICENSE
├── pyproject.toml // pyproject
├── setup.py // setup
└── README.md

基于定义的头文件,先生成代码

  • api_build.py
from cffi import FFI

ffibuilder = FFI()
ffibuilder.set_source("easytier.easytier_cffi", None)
with open("easytier.h") as f:
    ffibuilder.cdef(f.read())

if __name__ == '__main__':
    ffibuilder.compile(verbose=True)
  • easytier/__init__.py

比较简单,其他的暂时没包含

import os
import sys
from .easytier_cffi import ffi

class EasyTier:
    def __init__(self):
        # 基于操作系统加载lib
        lib_dir = os.path.join(os.path.dirname(__file__), 'lib')
        if sys.platform == 'win32':
            lib_path = os.path.join(lib_dir, 'easytier_ffi.dll')
        elif sys.platform == 'darwin':
            lib_path = os.path.join(lib_dir, 'libeasytier_ffi.dylib')
        else:
            lib_path = os.path.join(lib_dir, 'libeasytier_ffi.so')
        self.libeasytier = ffi.dlopen(lib_path)
    # 解析check
    def parse_config(self, config: str) -> int:
        """
        Parse the configuration string into a list of key-value pairs.
        :param config: Configuration string to parse.
        :return: List of key-value pairs as dictionaries.
        """
        return self.libeasytier.parse_config(config.encode('utf-8'))
    #  运行网络
    def run_network_instance(self, config: str) -> int:
        """
        Run the network instance with the given configuration.
        This method uses the EasyTier CFFI bindings to execute a network instance
        :param config: Configuration for the network instance.
        :return: Result of running the network instance.
        """
        return self.libeasytier.run_network_instance(config.encode('utf-8'))
    
__doc__ = "easytier: A Python wrapper for EasyTier CFFI bindings" 

__version__= "0.1.0"
  • setup基于setup的标准模块
from setuptools import setup,find_packages

setup(
    name="easytier",
    version="0.1.0",
    packages=["easytier"],
    setup_requires=["cffi>=1.17.1"],
    install_requires=["cffi>=1.17.1"],
    package_data={
        "easytier": ["lib/*.dylib", "lib/*.so","lib/*.dll"],
    },
    author="dalongrong",
    author_email="1141591465@qq.com",
    classifiers=[
        "Programming Language :: Python :: 3",
        "Operating System :: OS X",
        "Operating System :: POSIX",
    ],
    cffi_modules=["api_build.py:ffibuilder"],
    zip_safe=False,
)

构建&使用

  • 构建
python -m build --wheel
  • 使用

app.py 配参考

instance_name = "xxxxxx"
instance_id = "xxxxxx"
dhcp = true
listeners = [
    "tcp://0.0.0.0:11010",
    "udp://0.0.0.0:11010",
    "wg://0.0.0.0:11011",
]
rpc_portal = "0.0.0.0:0"

[network_identity]
network_name = "xxxxxx"
network_secret = "xxxxxx"

[[peer]]
uri = "tcp://xxxxxxx:11010"

[flags]

app.py

import easytier
import time
easy = easytier.EasyTier()

with open("app.yaml","r") as f:
    config = f.read()

result = easy.parse_config(config)
if result != 0:
    print("Error parsing configuration:", easy.get_error_msg())
    exit(1)
else:
    print("Configuration parsed successfully.")

result = easy.run_network_instance(config)

if result == 0:
    print("Network instance started successfully.")
    while True:
        time.sleep(1)
        print("Running network instance...")

说明

当然如果不使用cffi ,我们可以直接使用内置的ctypes 也是一种不错的选择,实际上vosk-api python 的处理就使用了类似的方法, 目前只是一个简单的示例,后续完善下其他api,代码我已经提交github 了

参考资料

https://github.com/rongfengliang/easytier-ffi-python

https://cffi.readthedocs.io/en/stable/

https://github.com/python-cffi/cffi

https://github.com/alphacep/vosk-api/tree/master/python

posted on 2025-08-15 08:00  荣锋亮  阅读(25)  评论(0)    收藏  举报

导航