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/