diff --git a/meson.build b/meson.build index 35974852b..8d5bdd812 100644 --- a/meson.build +++ b/meson.build @@ -40,6 +40,7 @@ subdir('include') subdir('src') subdir('dbus') subdir('netplan') +subdir('python-cffi') subdir('examples') subdir('doc') diff --git a/python-cffi/.gitignore b/python-cffi/.gitignore new file mode 100644 index 000000000..789470f7f --- /dev/null +++ b/python-cffi/.gitignore @@ -0,0 +1,4 @@ +_libnetplan*.c +_libnetplan*.o +_libnetplan*.so + diff --git a/python-cffi/__init__.py b/python-cffi/__init__.py new file mode 100644 index 000000000..54a2ca587 --- /dev/null +++ b/python-cffi/__init__.py @@ -0,0 +1,18 @@ +# Copyright (C) 2023 Canonical, Ltd. +# Author: Lukas Märdian +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Re-export submodules +from .parser import * +from .state import * \ No newline at end of file diff --git a/python-cffi/_build_cffi.py b/python-cffi/_build_cffi.py new file mode 100644 index 000000000..9a87de8c0 --- /dev/null +++ b/python-cffi/_build_cffi.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2023 Canonical, Ltd. +# Author: Lukas Märdian +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os + +from cffi import FFI +ffibuilder = FFI() + +# cdef() expects a single string declaring the C types, functions and +# globals needed to use the shared object. It must be in valid C syntax. +ffibuilder.cdef(""" + typedef int gint; + typedef gint gboolean; + typedef struct GError NetplanError; + typedef struct netplan_parser NetplanParser; + typedef struct netplan_state NetplanState; + typedef enum { + NETPLAN_BACKEND_NONE, + NETPLAN_BACKEND_NETWORKD, + NETPLAN_BACKEND_NM, + NETPLAN_BACKEND_OVS, + NETPLAN_BACKEND_MAX_, + } NetplanBackend; + + NetplanParser* netplan_parser_new(); + void netplan_parser_clear(NetplanParser **npp); + gboolean netplan_parser_load_yaml(NetplanParser* npp, const char* filename, NetplanError** error); + gboolean netplan_parser_load_yaml_from_fd(NetplanParser* npp, int input_fd, NetplanError** error); + //gboolean netplan_parser_load_yaml_hierarchy(NetplanParser* npp, const char* rootdir, GError** error); + gboolean netplan_parser_load_keyfile(NetplanParser* npp, const char* filename, NetplanError** error); + gboolean netplan_parser_load_nullable_fields(NetplanParser* npp, int input_fd, NetplanError** error); + //gboolean netplan_parser_load_nullable_overrides(NetplanParser* npp, int input_fd, const char* constraint, GError** error); + + NetplanState* netplan_state_new(); + void netplan_state_reset(NetplanState* np_state); + void netplan_state_clear(NetplanState** np_state); + NetplanBackend netplan_state_get_backend(const NetplanState* np_state); +""") + +# set_source() gives the name of the python extension module to +# produce, and some C source code as a string. This C code needs +# to make the declarated functions, types and globals available, +# so it is often just the "#include". +ffibuilder.set_source_pkgconfig("_libnetplan0", ['glib-2.0'], +""" + // the C header of the library + #include "netplan/netplan.h" + #include "netplan/parse.h" + #include "netplan/parse-nm.h" +""", + include_dirs=[os.getenv('CFFI_INC')], + library_dirs=[os.getenv('CFFI_LIB')], + libraries=['netplan', 'glib-2.0']) # library name, for the linker + +if __name__ == "__main__": + ffibuilder.compile(verbose=False) diff --git a/python-cffi/meson.build b/python-cffi/meson.build new file mode 100644 index 000000000..5d890f898 --- /dev/null +++ b/python-cffi/meson.build @@ -0,0 +1,26 @@ +pymod = import('python') +python = pymod.find_installation( + 'python3', + modules: ['cffi'] +) + +#https://mesonbuild.com/FAQ.html#but-i-really-want-to-use-wildcards +out = run_command( + 'sh', '-c', 'python3 _build_cffi.py && find -name _libnetplan*.so', + env: [ + 'CFFI_INC=join_paths(meson.project_source_root(), "include")', + 'CFFI_LIB=join_paths(meson.current_build_dir(), "src")', + ], + check: true, +) +cffi_so = out.stdout().strip().split('\n') + +bindings_sources = ''' + __init__.py + parser.py + state.py +'''.split() + +bindings = python.install_sources( + [bindings_sources, cffi_so], + subdir: 'netplan') diff --git a/python-cffi/parser.py b/python-cffi/parser.py new file mode 100644 index 000000000..538766831 --- /dev/null +++ b/python-cffi/parser.py @@ -0,0 +1,24 @@ +# Copyright (C) 2023 Canonical, Ltd. +# Author: Lukas Märdian +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from ._libnetplan0 import ffi, lib + +class Parser(): + def __init__(self): + self._ptr = lib.netplan_parser_new() + + def __del__(self): + ref = ffi.new('NetplanParser **', self._ptr) + lib.netplan_parser_clear(ref) diff --git a/python-cffi/state.py b/python-cffi/state.py new file mode 100644 index 000000000..908d79284 --- /dev/null +++ b/python-cffi/state.py @@ -0,0 +1,21 @@ +# Copyright (C) 2023 Canonical, Ltd. +# Author: Lukas Märdian +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from ._libnetplan0 import ffi, lib + +class State(): + def __init__(self): + state = lib.netplan_state_new() + print(lib.netplan_state_get_backend(state))