libeasytier-ffi ctypes 集成

主要是为了方便python 使用,基于ctypes包装一个,相比基于cffi 的安装比较方便,以下是简单说明

代码结构

代码基于flit 进行包管理

  • 结构
├── app.py
├── app.yaml
├── ctypes_easytier_ffi
│   ├── __init__.py
│   └── lib
│       ├── libeasytier_ffi.dylib
│       └── libeasytier_ffi.so
├── LICENSE
├── pyproject.toml
└── README.md
  • ctypes_easytier_ffi 代码

比较简单,就是类型以及方法定义,同时为了方便直接讲库放到包中了

import ctypes
from ctypes import c_char_p, c_int32, POINTER, Structure, c_size_t

# 定义结构体 KeyValuePair
class KeyValuePair(Structure):
    _fields_ = [
        ('key', c_char_p),
        ('value', c_char_p),
    ]

def find_library():
    import os
    import sys
    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')
    if not os.path.exists(lib_path):
        raise FileNotFoundError(f"Library not found.")
    return lib_path

lib = ctypes.CDLL(find_library())

# void get_error_msg(const char **out);
lib.get_error_msg.argtypes = [POINTER(c_char_p)]
lib.get_error_msg.restype = None

# void free_string(char* s);
lib.free_string.argtypes = [c_char_p]
lib.free_string.restype = None

# int32_t parse_config(const char* cfg_str);
lib.parse_config.argtypes = [c_char_p]
lib.parse_config.restype = c_int32

# int32_t run_network_instance(const char* cfg_str);
lib.run_network_instance.argtypes = [c_char_p]
lib.run_network_instance.restype = c_int32

# int32_t retain_network_instance(const char** inst_names, uintptr_t length);
lib.retain_network_instance.argtypes = [POINTER(c_char_p), c_size_t]
lib.retain_network_instance.restype = c_int32

# int32_t collect_network_infos(KeyValuePair* infos, uintptr_t max_length);
lib.collect_network_infos.argtypes = [POINTER(KeyValuePair), c_size_t]
lib.collect_network_infos.restype = c_int32


__version__ = "0.1.0"

__doc__ = """
ctypes_easytier_ffi - A Python FFI for EasyTier
"""

使用

基于配置方便测试

  • 测试代码

app.yaml 方便测试配置

instance_name = "xxxx"
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 = "xxxxx"
network_secret = "xxxxx"

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

[flags]

app.py

import time
from ctypes_easytier_ffi import lib, KeyValuePair

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

result = lib.run_network_instance(config.encode())

if result == 0:
    print("Network instance started successfully.")
    while True:
        try:
            print("Collecting network infos...")
            time.sleep(3)
            MAX_LEN = 10
            infos = (KeyValuePair * MAX_LEN)()
            result = lib.collect_network_infos(infos, MAX_LEN)
            for i in range(result):
                print(f"{infos[i].key.decode()} => {infos[i].value.decode()}")
        except Exception as e:
            print(f"An error occurred: {e}")
            break

说明

基于ctypes 的特定就是比较方便,没有cffi 那些复杂的依赖,直接使用就可以了,代码我已经push github了

参考资料

https://github.com/rongfengliang/easytier-ffii-ctypes

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

https://github.com/EasyTier/EasyTier/tree/main/easytier-contrib/easytier-ffi

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

导航