From 178312aa139fc4349ac32720ce23b8fde6cb7910 Mon Sep 17 00:00:00 2001 From: Mikael Bourhis Date: Wed, 11 Oct 2023 11:00:28 +0200 Subject: [PATCH 1/3] Python wrapper: update CMakeLists, and rename the module to 'pyiec61850' * update the CMakeLists - remove the deprecated commands ('PythonInterp', ...) (https://cmake.org/cmake/help/latest/module/FindPythonInterp.html) - change the CMake minimum version from 3.8 to 3.12 (released in July 2018) * rename the libiec61850 Python module into 'pyiec61850' - to avoid name conflict with the name for the C static lib - the build artifacts are now 'pyiec61850.py' and '_pyiec61850.so' Signed-off-by: Mikael Bourhis --- pyiec61850/CMakeLists.txt | 33 ++++++++----------- pyiec61850/examples/dispServerStruct.py | 2 +- pyiec61850/examples/rcbSubscriptionExample.py | 2 +- pyiec61850/iec61850.i | 2 +- pyiec61850/test_pyiec61850.py | 2 +- pyiec61850/tutorial.md | 19 +++++++++-- 6 files changed, 34 insertions(+), 26 deletions(-) diff --git a/pyiec61850/CMakeLists.txt b/pyiec61850/CMakeLists.txt index 159ef4bc..ce03da9c 100644 --- a/pyiec61850/CMakeLists.txt +++ b/pyiec61850/CMakeLists.txt @@ -1,14 +1,13 @@ -# The SWIG functions/macros used in this module, swig_add_module and swig_add_library -# are not available in CMake versions earlier than 3.8 -# cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.12) + +set(CMAKE_POLICY_DEFAULT_CMP0078 NEW) find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) -find_package(PythonInterp ${BUILD_PYTHON_VERSION} REQUIRED) -find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT REQUIRED) +find_package(Python COMPONENTS Interpreter Development REQUIRED) -include_directories(${PYTHON_INCLUDE_PATH}) +include_directories(${Python_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_SWIG_FLAGS "") @@ -20,25 +19,21 @@ else() set(LIBS iec61850-shared) endif() -if(${CMAKE_VERSION} VERSION_LESS 3.8) - swig_add_module(iec61850 python iec61850.i) -else() - swig_add_library(iec61850 - LANGUAGE python - SOURCES iec61850.i - ) -endif() +swig_add_library(pyiec61850 + LANGUAGE python + SOURCES iec61850.i +) -swig_link_libraries(iec61850 ${PYTHON_LIBRARIES} ${LIBS}) +swig_link_libraries(pyiec61850 ${LIBS}) # Finding python modules install path execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c + COMMAND ${Python_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; import sys; sys.stdout.write(get_python_lib())" OUTPUT_VARIABLE PYTHON_SITE_DIR ) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/iec61850.py DESTINATION ${PYTHON_SITE_DIR}) -install(TARGETS _iec61850 LIBRARY DESTINATION ${PYTHON_SITE_DIR}) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pyiec61850.py DESTINATION ${PYTHON_SITE_DIR}) +install(TARGETS pyiec61850 LIBRARY DESTINATION ${PYTHON_SITE_DIR}) -add_test(test_pyiec61850 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/test_pyiec61850.py) +add_test(test_pyiec61850 ${Python_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/test_pyiec61850.py) diff --git a/pyiec61850/examples/dispServerStruct.py b/pyiec61850/examples/dispServerStruct.py index aea02b4f..2b49479b 100755 --- a/pyiec61850/examples/dispServerStruct.py +++ b/pyiec61850/examples/dispServerStruct.py @@ -1,6 +1,6 @@ #!/usr/bin/python import os,sys -import iec61850 +import pyiec61850 as iec61850 if __name__=="__main__": hostname = "localhost"; tcpPort = 102 diff --git a/pyiec61850/examples/rcbSubscriptionExample.py b/pyiec61850/examples/rcbSubscriptionExample.py index d4d05aa5..7d1243be 100644 --- a/pyiec61850/examples/rcbSubscriptionExample.py +++ b/pyiec61850/examples/rcbSubscriptionExample.py @@ -27,7 +27,7 @@ The user needs to: import time import sys -import iec61850 +import pyiec61850 as iec61850 def open_connection(ip_address, mms_port): diff --git a/pyiec61850/iec61850.i b/pyiec61850/iec61850.i index 254fec64..4cdbe0ea 100644 --- a/pyiec61850/iec61850.i +++ b/pyiec61850/iec61850.i @@ -1,5 +1,5 @@ /* File : iec61850.i */ -%module(directors="1") iec61850 +%module(directors="1") pyiec61850 %ignore ControlObjectClient_setTestMode(ControlObjectClient self); %ignore CDA_OperBoolean(ModelNode* parent, bool isTImeActivated); %ignore LogicalNode_hasBufferedReports(LogicalNode* node); diff --git a/pyiec61850/test_pyiec61850.py b/pyiec61850/test_pyiec61850.py index aceb3fdb..6f6d8cdd 100755 --- a/pyiec61850/test_pyiec61850.py +++ b/pyiec61850/test_pyiec61850.py @@ -6,7 +6,7 @@ import traceback import signal import sys sys.path.append('.') -import iec61850 +import pyiec61850 as iec61850 def signal_handler(signal, frame): global running running =0 diff --git a/pyiec61850/tutorial.md b/pyiec61850/tutorial.md index ce766cab..1e6b4f4f 100644 --- a/pyiec61850/tutorial.md +++ b/pyiec61850/tutorial.md @@ -2,14 +2,27 @@ Before building you should install swig and python. To build python bindings you have to turn on the BUILD\_PYTHON\_BINDINGS flag in CMake from cmake-gui or in command line: ```sh -$ cmake -DBUILD_PYTHON_BINDINGS=ON . +$ mkdir build && cd build +$ cmake -DBUILD_PYTHON_BINDINGS=ON .. +``` + +Then compile the library and install it: +```sh +$ make +$ sudo make install +``` +CMake and swig will automatically detect your python version and install the python library in python library directories. + +For running the integrated tests: +```sh +$ make test ``` -Then compile the library and install it. CMake and swig will automatically detect your python version and install the python library in python library directories. pyiec61850 library is to be imported calling ```python -import iec61850 +import pyiec61850 as iec61850 ``` + # Client tutorial The python bindings works similarly to the basic C library. However there are some differences: From 0f0d22ab61a5d252830e67e20906070b52cbe95a Mon Sep 17 00:00:00 2001 From: Mikael Bourhis Date: Wed, 25 Oct 2023 16:22:49 +0200 Subject: [PATCH 2/3] Python wrapper: update and improve CMakeLists Tested and compatible with: Ubuntu 20.04.6 LTS : Python 3.8.10; CMake 3.16.3; Swig 4.0.1 Debian 11 : Python 3.9.2; CMake 3.13.4; Swig 4.0.2 Ubuntu 22.04.3 LTS : Python 3.10.12; CMake 3.22.1; Swig 4.0.2 Ubuntu 23.10 : Python 3.11.6; CMake 3.27.4; Swig 4.1.0 Alpine 3.18.4 : Python 3.11.6; CMake 3.26.5; Swig 4.1.1 Signed-off-by: Mikael Bourhis --- pyiec61850/CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pyiec61850/CMakeLists.txt b/pyiec61850/CMakeLists.txt index ce03da9c..a42960f9 100644 --- a/pyiec61850/CMakeLists.txt +++ b/pyiec61850/CMakeLists.txt @@ -1,6 +1,10 @@ cmake_minimum_required(VERSION 3.12) -set(CMAKE_POLICY_DEFAULT_CMP0078 NEW) +cmake_policy(SET CMP0078 NEW) + +if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14.0") + cmake_policy(SET CMP0086 NEW) +endif() find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) @@ -12,6 +16,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_SWIG_FLAGS "") set_property(SOURCE iec61850.i PROPERTY CPLUSPLUS ON) +set_property(SOURCE iec61850.i PROPERTY SWIG_MODULE_NAME pyiec61850) if(WIN32) set(LIBS iec61850 ws2_32) @@ -29,7 +34,7 @@ swig_link_libraries(pyiec61850 ${LIBS}) # Finding python modules install path execute_process( COMMAND ${Python_EXECUTABLE} -c - "from distutils.sysconfig import get_python_lib; import sys; sys.stdout.write(get_python_lib())" + "from sysconfig import get_path; import sys; sys.stdout.write(get_path('platlib'))" OUTPUT_VARIABLE PYTHON_SITE_DIR ) From 65847e4ffec6e9d68dbcbebf31238a2bbefe8e8d Mon Sep 17 00:00:00 2001 From: Mikael Bourhis Date: Thu, 26 Oct 2023 12:31:00 +0200 Subject: [PATCH 3/3] Python wrapper: update the README file Signed-off-by: Mikael Bourhis --- pyiec61850/{tutorial.md => README.md} | 46 +++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 7 deletions(-) rename pyiec61850/{tutorial.md => README.md} (54%) diff --git a/pyiec61850/tutorial.md b/pyiec61850/README.md similarity index 54% rename from pyiec61850/tutorial.md rename to pyiec61850/README.md index 1e6b4f4f..b2398919 100644 --- a/pyiec61850/tutorial.md +++ b/pyiec61850/README.md @@ -1,6 +1,10 @@ -# Building -Before building you should install swig and python. -To build python bindings you have to turn on the BUILD\_PYTHON\_BINDINGS flag in CMake from cmake-gui or in command line: +# Python wrapper for libIEC61850 + +## Building +Before building you should install SWIG and Python +(see the '[Setup development environment on Linux](#setup-development-environment-on-linux-ubuntu)' section for help). + +To build the Python bindings you have to turn on the BUILD\_PYTHON\_BINDINGS flag in CMake from cmake-gui or in command line: ```sh $ mkdir build && cd build $ cmake -DBUILD_PYTHON_BINDINGS=ON .. @@ -11,21 +15,23 @@ Then compile the library and install it: $ make $ sudo make install ``` -CMake and swig will automatically detect your python version and install the python library in python library directories. +(Eventually, update your ld cache with: `sudo ldconfig`) + +CMake and SWIG will automatically detect your Python version and install the Python library in Python library directories. For running the integrated tests: ```sh $ make test ``` -pyiec61850 library is to be imported calling +pyiec61850 library is to be imported calling: ```python import pyiec61850 as iec61850 ``` -# Client tutorial +## Client tutorial -The python bindings works similarly to the basic C library. However there are some differences: +The Python bindings works similarly to the basic C library. However there are some differences: * a specific function is to be called to cast variables from one type to another * arguments passed by pointer are to be removed from arguments and append to the return list @@ -61,3 +67,29 @@ Reading and writing operations can be performed using this syntax: err = iec61850.IedConnection_writeFloatValue(con, "simpleIOGenericIO/GGIO1.AnIn1.mag.f", iec61850.IEC61850_FC_MX, 10.0) ``` + +## Appendix + +## Setup development environment on Linux Ubuntu + +_[Tested on Ubuntu 20.04 LTS, Ubuntu 22.04 LTS, Ubuntu 23.10]_ + +Here the minimum required packages for compiling libiec61850 and the Python +wrapper (without TLS, SQlite, ...): + +```sh +$ sudo apt-get update +$ sudo apt-get install g++ cmake swig git python3 python3-all-dev +``` + +## Setup development environment on Linux Alpine + +_[Tested on Alpine 3.18]_ + +Here the minimum required packages for compiling libiec61850 and the Python +wrapper (without TLS, SQlite, ...): + +```sh +$ apk update +$ apk add git g++ swig make cmake python3 python3-dev linux-headers +```