From 8a7cecb43ea8a3c887b3c7949ff512fadc756ae9 Mon Sep 17 00:00:00 2001 From: David Wagner Date: Tue, 6 Jan 2015 11:03:06 +0100 Subject: Introduce Python bindings These bindings for the parameter-framework generic connector use "SWIG" to generate: - a C++ file providing a basic bridge between C++ and Python (must be compiled to a shared library named "_PyPfw.so" - the name is important) - a Python module wrapping it inside a Proxy class, re-creating the same classes as the parameter-framework generic connector. See http://www.swig.org for the full SWIG documentation. They are generated and compiled on-the-fly as part of the build process. Change-Id: If7c67f1178dcc9f438cf037246eb77bbd74b689a Signed-off-by: David Wagner Signed-off-by: Sebastien Gonzalve --- bindings/Android.mk | 5 ++ bindings/CMakeLists.txt | 29 +++++++ bindings/python/Android.mk | 81 ++++++++++++++++++ bindings/python/CMakeLists.txt | 58 +++++++++++++ bindings/python/pfw.i | 189 +++++++++++++++++++++++++++++++++++++++++ bindings/python/sample.py | 45 ++++++++++ 6 files changed, 407 insertions(+) create mode 100644 bindings/Android.mk create mode 100644 bindings/CMakeLists.txt create mode 100644 bindings/python/Android.mk create mode 100644 bindings/python/CMakeLists.txt create mode 100644 bindings/python/pfw.i create mode 100755 bindings/python/sample.py (limited to 'bindings') diff --git a/bindings/Android.mk b/bindings/Android.mk new file mode 100644 index 0000000..f5f1064 --- /dev/null +++ b/bindings/Android.mk @@ -0,0 +1,5 @@ +# Recursive call sub-folder Android.mk +# + +include $(call all-subdir-makefiles) + diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt new file mode 100644 index 0000000..3208d54 --- /dev/null +++ b/bindings/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2015, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +add_subdirectory(python) diff --git a/bindings/python/Android.mk b/bindings/python/Android.mk new file mode 100644 index 0000000..2cfd13d --- /dev/null +++ b/bindings/python/Android.mk @@ -0,0 +1,81 @@ +# Copyright (c) 2015, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +LOCAL_PATH := $(call my-dir) + +# Low-level python wrapper +include $(CLEAR_VARS) +# When importing a python module from a shared library, the name of the lib has +# to be exactly the same as the module name it contains. SWIG generates a +# python module called "PyPfw" that relies on the one that we are building as a +# shared library here, and that is named "_PyPfw" +# See https://docs.python.org/2/extending/extending.html#the-module-s-method-table-and-initialization-function +LOCAL_MODULE := _PyPfw + +LOCAL_CPP_EXTENSION := .cxx + +LOCAL_SHARED_LIBRARIES := libparameter_host +LOCAL_STATIC_LIBRARIES := libxmlserializer_host + +LOCAL_C_INCLUDES := \ + prebuilts/python/linux-x86/2.7.5/include/python2.7 \ + $(HOST_OUT_HEADERS)/parameter + +# The 'unused-but-set-variable' warning must be disabled because SWIG generates +# files that do not respect that constraint. +LOCAL_CFLAGS := -Wno-unused-but-set-variable -fexceptions + +# Undefined symbols will be resolved at runtime +LOCAL_ALLOW_UNDEFINED_SYMBOLS := true + +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_OWNER := intel + +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_IS_HOST_MODULE := true + +generated-sources-dir := $(call local-generated-sources-dir) + +LOCAL_GENERATED_SOURCES := $(generated-sources-dir)/pfw_wrap.cxx $(generated-sources-dir)/pfw_wrap.h + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(generated-sources-dir) + +$(generated-sources-dir)/pfw_wrap.h: $(generated-sources-dir)/pfw_wrap.cxx + +# The PyPfw.py file is generated in the directory given by -outdir switch, thus +# this directory must be put in the python path to be reachable +$(generated-sources-dir)/pfw_wrap.cxx: $(LOCAL_PATH)/pfw.i + @echo "Generating Python binding files" + mkdir -p $(dir $@) # surprisingly, path is not generated by build system + prebuilts/misc/linux-x86_64/swig/swig \ + -Iprebuilts/misc/common/swig/include/2.0.11/python/ \ + -Iprebuilts/misc/common/swig/include/2.0.11/ \ + -Wall -Werror -v -python -c++ -outdir $(HOST_LIBRARY_PATH)/ -o $@ $^ + +include $(BUILD_HOST_SHARED_LIBRARY) + diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt new file mode 100644 index 0000000..535c920 --- /dev/null +++ b/bindings/python/CMakeLists.txt @@ -0,0 +1,58 @@ +# Copyright (c) 2015, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FIND_PACKAGE(SWIG REQUIRED) +INCLUDE(${SWIG_USE_FILE}) + +FIND_PACKAGE(PythonLibs) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +SET_SOURCE_FILES_PROPERTIES(pfw.i PROPERTIES CPLUSPLUS ON) +SET_SOURCE_FILES_PROPERTIES(pfw.i PROPERTIES SWIG_FLAGS "-v" "-Wall" "-Werror") + +SWIG_ADD_MODULE(PyPfw python pfw.i) +SWIG_LINK_LIBRARIES(PyPfw parameter ${PYTHON_LIBRARIES}) + +include(FindPythonLibs) +if(NOT PYTHONLIBS_FOUND) + message(SEND_ERROR "python librarires not found. please instal python + development packages") +endif(NOT PYTHONLIBS_FOUND) + +include_directories(${PROJECT_SOURCE_DIR}/parameter/include ${PYTHON_INCLUDE_DIRS}) + +# Add some exceptions because files generated by SWIG are not +# "-Wextra"-compliant +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-variable") + +install(TARGETS _PyPfw LIBRARY DESTINATION lib) + +# install the generated Python file as well +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/PyPfw.py DESTINATION lib) diff --git a/bindings/python/pfw.i b/bindings/python/pfw.i new file mode 100644 index 0000000..c029d13 --- /dev/null +++ b/bindings/python/pfw.i @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2015, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +%module PyPfw + +%include "std_string.i" +%include "std_vector.i" +%include "typemaps.i" + +// We need to tell SWIG that std::vector is a vector of strings +namespace std { + %template(StringVector) vector; +} + +// Tells swig that 'std::string& strError' must be treated as output parameters +// TODO: make it return a tuple instead of a list +%apply std::string &OUTPUT { std::string& strError }; + +// Automatic python docstring generation +// FIXME: because of the typemap above, the output type is wrong for methods +// that can return an error string. +// TODO: document each function manually ? +%feature("autodoc", "1"); + + +// rename "CParameterMgrFullConnector" into the nicer "ParameterFramework" name +%rename(ParameterFramework) CParameterMgrFullConnector; +class CParameterMgrFullConnector +{ + +%{ +#include "ParameterMgrFullConnector.h" +%} + +public: + CParameterMgrFullConnector(const std::string& strConfigurationFilePath); + + bool start(std::string& strError); + + ISelectionCriterionTypeInterface* createSelectionCriterionType(bool bIsInclusive); + ISelectionCriterionInterface* createSelectionCriterion(const std::string& strName, + const ISelectionCriterionTypeInterface* pSelectionCriterionType); + ISelectionCriterionInterface* getSelectionCriterion(const std::string& strName); + + // Configuration application + void applyConfigurations(); + + void setFailureOnMissingSubsystem(bool bFail); + bool getFailureOnMissingSubsystem() const; + + void setFailureOnFailedSettingsLoad(bool bFail); + bool getFailureOnFailedSettingsLoad(); + + void setSchemaFolderLocation(const std::string& strSchemaFolderLocation); + void setValidateSchemasOnStart(bool bValidate); + bool getValidateSchemasOnStart() const; + + // Tuning mode + bool setTuningMode(bool bOn, std::string& strError); + bool isTuningModeOn() const; + + // Current value space for user set/get value interpretation + void setValueSpace(bool bIsRaw); + bool isValueSpaceRaw() const; + + // Current Output Raw Format for user get value interpretation + void setOutputRawFormat(bool bIsHex); + bool isOutputRawFormatHex() const; + + // Automatic hardware synchronization control (during tuning session) + bool setAutoSync(bool bAutoSyncOn, std::string& strError); + bool isAutoSyncOn() const; + bool sync(std::string& strError); + + // User set/get parameters +%apply std::string &INOUT { std::string& strValue }; + bool accessParameterValue(const std::string& strPath, std::string& strValue, bool bSet, std::string& strError); + bool accessConfigurationValue(const std::string &strDomain, const std::string &strConfiguration, const std::string& strPath, std::string& strValue, bool bSet, std::string& strError); +%clear std::string& strValue; + + bool getParameterMapping(const std::string& strPath, std::string& strValue) const; + + // Creation/Deletion + bool createDomain(const std::string& strName, std::string& strError); + bool deleteDomain(const std::string& strName, std::string& strError); + bool renameDomain(const std::string& strName, const std::string& strNewName, std::string& strError); + bool deleteAllDomains(std::string& strError); +%apply std::string &OUTPUT { std::string& strResult } + bool setSequenceAwareness(const std::string& strName, bool bSequenceAware, std::string& strResult); + bool getSequenceAwareness(const std::string& strName, bool& bSequenceAware, std::string& strResult); +%clear std::string& strResult; + bool createConfiguration(const std::string& strDomain, const std::string& strConfiguration, std::string& strError); + bool deleteConfiguration(const std::string& strDomain, const std::string& strConfiguration, std::string& strError); + bool renameConfiguration(const std::string& strDomain, const std::string& strConfiguration, const std::string& strNewConfiguration, std::string& strError); + + // Save/Restore + bool restoreConfiguration(const std::string& strDomain, const std::string& strConfiguration, std::list& strError); + bool saveConfiguration(const std::string& strDomain, const std::string& strConfiguration, std::string& strError); + + // Configurable element - domain association + bool addConfigurableElementToDomain(const std::string& strDomain, const std::string& strConfigurableElementPath, std::string& strError); + bool removeConfigurableElementFromDomain(const std::string& strDomain, const std::string& strConfigurableElementPath, std::string& strError); + bool split(const std::string& strDomain, const std::string& strConfigurableElementPath, std::string& strError); + bool setElementSequence(const std::string& strDomain, const std::string& strConfiguration, const std::vector& astrNewElementSequence, std::string& strError); + + bool setApplicationRule(const std::string& strDomain, const std::string& strConfiguration, const std::string& strApplicationRule, std::string& strError); +%apply std::string &OUTPUT { std::string& strResult } + bool getApplicationRule(const std::string& strDomain, const std::string& strConfiguration, std::string& strResult); +%clear std::string& strResult; + bool clearApplicationRule(const std::string& strDomain, const std::string& strConfiguration, std::string& strError); + + bool importDomainsXml(const std::string& strXmlSource, bool bWithSettings, bool bFromFile, + std::string& strError); + bool importSingleDomainXml(const std::string& strXmlSource, bool bOverwrite, + std::string& strError); + +// Tells swig that "strXmlDest" in the two following methods are "inout" +// parameters +%apply std::string &INOUT { std::string& strXmlDest }; + bool exportDomainsXml(std::string& strXmlDest, bool bWithSettings, bool bToFile, + std::string& strError) const; + + bool exportSingleDomainXml(std::string& strXmlDest, const std::string& strDomainName, bool bWithSettings, + bool bToFile, std::string& strError) const; +%clear std::string& strXmlDest; + +%apply std::string &OUTPUT { std::string& strResult } + bool getSystemClassXMLString(std::string& strResult); +%clear std::string& strResult; +}; + +class ISelectionCriterionTypeInterface +{ +%{ +#include "SelectionCriterionTypeInterface.h" +%} + +public: + virtual bool addValuePair(int iValue, const std::string& strValue) = 0; + virtual bool getNumericalValue(const std::string& strValue, int& iValue) const = 0; + virtual bool getLiteralValue(int iValue, std::string& strValue) const = 0; + virtual bool isTypeInclusive() const = 0; + virtual std::string getFormattedState(int iValue) const = 0; + +protected: + virtual ~ISelectionCriterionTypeInterface() {} +}; + +class ISelectionCriterionInterface +{ +%{ +#include "SelectionCriterionInterface.h" +%} + +public: + virtual void setCriterionState(int iState) = 0; + virtual int getCriterionState() const = 0; + virtual std::string getCriterionName() const = 0; + virtual const ISelectionCriterionTypeInterface* getCriterionType() const = 0; + +protected: + virtual ~ISelectionCriterionInterface() {} +}; diff --git a/bindings/python/sample.py b/bindings/python/sample.py new file mode 100755 index 0000000..f33ddeb --- /dev/null +++ b/bindings/python/sample.py @@ -0,0 +1,45 @@ +#! /usr/bin/env python +# Copyright (c) 2015, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import PyPfw +import sys + +pfw = PyPfw.ParameterFramework(sys.argv[1]) + +moodType = pfw.createSelectionCriterionType(False) +for numerical, literal in enumerate(["mad", "sad", "glad"]): + moodType.addValuePair(numerical, literal) + +mood = pfw.createSelectionCriterion("Mood", moodType) + +ok, error = pfw.start() +if not ok: + print("Error while starting the pfw: {}".format(error)) + +raw_input("[Press enter to exit]") -- cgit v1.1