aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2018-05-08 14:15:57 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2018-05-16 09:11:43 +0000
commit15273fe0fe52569013dd4811bf9ed770ce7fb287 (patch)
treef58eab1b18998592f8f9dd541232b58253529aad /examples
parent9d9144b2b44677d2862e389b7a83900ee3e8e44c (diff)
Add an example that demonstrates bindings to a custom C++ library
A CMake project is included that builds two shared libraries: 1) libuniverse - a hypothetical C++ library for which bindings need to be created. 2) Universe - a Python module containing bindings to the above library. The example showcases the following concepts: * primitive type bindings (bool, std::string) * types with object and value semantics (pass by pointer VS pass by copy) * inheritance and overriding virtual methods * ownership of heap-allocated C++ objects * constructors with default parameters * general structure of CMakeLists.txt file for generating bindings Task-number: PYSIDE-597 Change-Id: I7b0f203e2844e815aa611af3de2b50a9aa9b5bfc Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'examples')
-rw-r--r--examples/samplebinding/CMakeLists.txt233
-rw-r--r--examples/samplebinding/README.md223
-rw-r--r--examples/samplebinding/bindings.h57
-rw-r--r--examples/samplebinding/bindings.xml80
-rw-r--r--examples/samplebinding/icecream.cpp65
-rw-r--r--examples/samplebinding/icecream.h71
-rw-r--r--examples/samplebinding/macros.h68
-rw-r--r--examples/samplebinding/main.py102
-rw-r--r--examples/samplebinding/truck.cpp138
-rw-r--r--examples/samplebinding/truck.h84
-rw-r--r--examples/scriptableapplication/CMakeLists.txt16
-rw-r--r--examples/scriptableapplication/pyside2.pri14
-rw-r--r--examples/utils/pyside2_config.py (renamed from examples/scriptableapplication/pyside2_config.py)33
13 files changed, 1162 insertions, 22 deletions
diff --git a/examples/samplebinding/CMakeLists.txt b/examples/samplebinding/CMakeLists.txt
new file mode 100644
index 000000000..03ab85754
--- /dev/null
+++ b/examples/samplebinding/CMakeLists.txt
@@ -0,0 +1,233 @@
+cmake_minimum_required(VERSION 3.1)
+cmake_policy(VERSION 3.1)
+
+# Enable policy to not use RPATH settings for install_name on macOS.
+if(POLICY CMP0068)
+ cmake_policy(SET CMP0068 NEW)
+endif()
+
+# Consider changing the project name to something relevant for you.
+project(SampleBinding)
+
+# ================================ General configuration ======================================
+
+# Set CPP standard to C++11 minimum.
+set(CMAKE_CXX_STANDARD 11)
+
+# The sample library for which we will create bindings. You can change the name to something
+# relevant for your project.
+set(sample_library "libuniverse")
+
+# The name of the generated bindings module (as imported in Python). You can change the name
+# to something relevant for your project.
+set(bindings_library "Universe")
+
+# The header file with all the types and functions for which bindings will be generated.
+# Usually it simply includes other headers of the library you are creating bindings for.
+set(wrapped_header ${CMAKE_SOURCE_DIR}/bindings.h)
+
+# The typesystem xml file which defines the relationships between the C++ types / functions
+# and the corresponding Python equivalents.
+set(typesystem_file ${CMAKE_SOURCE_DIR}/bindings.xml)
+
+# Specify which C++ files will be generated by shiboken. This includes the module wrapper
+# and a '.cpp' file per C++ type. These are needed for generating the module shared
+# library.
+set(generated_sources
+ ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/universe_module_wrapper.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/icecream_wrapper.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/truck_wrapper.cpp)
+
+
+# ================================== Shiboken detection ======================================
+
+
+# Macro to get various pyside / python include / link flags and paths.
+# Uses the not entirely supported utils/pyside2_config.py file.
+macro(pyside2_config option output_var)
+ if(${ARGC} GREATER 2)
+ set(is_list ${ARGV2})
+ else()
+ set(is_list "")
+ endif()
+
+ execute_process(
+ COMMAND python "${CMAKE_SOURCE_DIR}/../utils/pyside2_config.py" ${option}
+ OUTPUT_VARIABLE ${output_var}
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ if ("${${output_var}}" STREQUAL "")
+ message(FATAL_ERROR "Error: Calling pyside2_config.py ${option} returned no output.")
+ endif()
+ if(is_list)
+ string (REPLACE " " ";" ${output_var} "${${output_var}}")
+ endif()
+endmacro()
+
+# Query for the shiboken path, Python path, include paths and linker flags.
+pyside2_config(--pyside2 pyside2_path)
+pyside2_config(--python-include python_include_dir)
+pyside2_config(--shiboken-include shiboken_include_dir 1)
+pyside2_config(--shiboken-shared-libraries-cmake shiboken_shared_libraries 0)
+pyside2_config(--python-link-cmake python_linking_data 0)
+
+set(shiboken_path "${pyside2_path}/shiboken2${CMAKE_EXECUTABLE_SUFFIX}")
+if(NOT EXISTS ${shiboken_path})
+ message(FATAL_ERROR "Shiboken executable not found at path: ${shiboken_path}")
+endif()
+
+
+# ==================================== RPATH configuration ====================================
+
+
+# =============================================================================================
+# !!! (The section below is deployment related, so in a real world application you will want to
+# take care of this properly with some custom script or tool).
+# =============================================================================================
+# Enable rpaths so that the built shared libraries find their dependencies.
+set(CMAKE_SKIP_BUILD_RPATH FALSE)
+set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
+set(CMAKE_INSTALL_RPATH ${pyside2_path} ${CMAKE_CURRENT_SOURCE_DIR})
+set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+# =============================================================================================
+# !!! End of dubious section.
+# =============================================================================================
+
+
+# =============================== CMake target - sample_library ===============================
+
+
+# Define the sample shared library for which we will create bindings.
+set(${sample_library}_sources icecream.cpp truck.cpp)
+add_library(${sample_library} SHARED ${${sample_library}_sources})
+set_property(TARGET ${sample_library} PROPERTY PREFIX "")
+
+# Needed mostly on Windows to export symbols, and create a .lib file, otherwise the binding
+# library can't link to the sample library.
+target_compile_definitions(${sample_library} PRIVATE BINDINGS_BUILD)
+
+
+# ====================== Shiboken target for generating binding C++ files ====================
+
+
+# Set up the options to pass to shiboken.
+set(shiboken_options --generator-set=shiboken --enable-parent-ctor-heuristic
+ --enable-return-value-heuristic --use-isnull-as-nb_nonzero
+ --avoid-protected-hack
+ -I${CMAKE_SOURCE_DIR}
+ -T${CMAKE_SOURCE_DIR}
+ --output-directory=${CMAKE_CURRENT_BINARY_DIR}
+ )
+
+set(generated_sources_dependencies ${wrapped_header} ${typesystem_file})
+
+# Add custom target to run shiboken to generate the binding cpp files.
+add_custom_command(OUTPUT ${generated_sources}
+ COMMAND ${shiboken_path}
+ ${shiboken_options} ${wrapped_header} ${typesystem_file}
+ DEPENDS ${generated_sources_dependencies}
+ IMPLICIT_DEPENDS CXX ${wrapped_header}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Running generator for ${typesystem_file}.")
+
+
+# =============================== CMake target - bindings_library =============================
+
+
+# Set the cpp files which will be used for the bindings library.
+set(${bindings_library}_sources ${generated_sources})
+
+# Define and build the bindings library.
+add_library(${bindings_library} MODULE ${${bindings_library}_sources})
+
+# Apply relevant include and link flags.
+target_include_directories(${bindings_library} PRIVATE ${python_include_dir})
+target_include_directories(${bindings_library} PRIVATE ${shiboken_include_dir})
+target_include_directories(${bindings_library} PRIVATE ${CMAKE_SOURCE_DIR})
+
+target_link_libraries(${bindings_library} PRIVATE ${shiboken_shared_libraries})
+target_link_libraries(${bindings_library} PRIVATE ${sample_library})
+
+# Adjust the name of generated module.
+set_property(TARGET ${bindings_library} PROPERTY PREFIX "")
+set_property(TARGET ${bindings_library} PROPERTY OUTPUT_NAME
+ "${bindings_library}${PYTHON_EXTENSION_SUFFIX}")
+if(WIN32)
+ set_property(TARGET ${bindings_library} PROPERTY SUFFIX ".pyd")
+endif()
+
+# Make sure the linker doesn't complain about not finding Python symbols on macOS.
+if(APPLE)
+ set_target_properties(${bindings_library} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
+endif(APPLE)
+
+# Find and link to the python import library only on Windows.
+# On Linux and macOS, the undefined symbols will get resolved by the dynamic linker
+# (the symbols will be picked up in the Python executable).
+if (WIN32)
+ list(GET python_linking_data 0 python_libdir)
+ list(GET python_linking_data 1 python_lib)
+ find_library(python_link_flags ${python_lib} PATHS ${python_libdir} HINTS ${python_libdir})
+ target_link_libraries(${bindings_library} PRIVATE ${python_link_flags})
+endif()
+
+
+# ================================= Dubious deployment section ================================
+
+
+if(WIN32)
+ # =========================================================================================
+ # !!! (The section below is deployment related, so in a real world application you will
+ # want to take care of this properly (this is simply to eliminate errors that users usually
+ # encounter.
+ # =========================================================================================
+ # Circumvent some "#pragma comment(lib)"s in "include/pyconfig.h" which might force to link
+ # against a wrong python shared library.
+
+ set(python_versions_list 3 32 33 34 35 36 37 38)
+ set(python_additional_link_flags "")
+ foreach(ver ${python_versions_list})
+ set(python_additional_link_flags
+ "${python_additional_link_flags} /NODEFAULTLIB:\"python${ver}_d.lib\"")
+ set(python_additional_link_flags
+ "${python_additional_link_flags} /NODEFAULTLIB:\"python${ver}.lib\"")
+ endforeach()
+
+ set_target_properties(${bindings_library}
+ PROPERTIES LINK_FLAGS "${python_additional_link_flags}")
+
+ # Add custom target to hard-link shiboken shared libraries into the build folder, so that
+ # the user doesn't have to set the PATH manually to point to the PySide2 package.
+ foreach(library_path ${shiboken_shared_libraries})
+ string(REGEX REPLACE ".lib$" ".dll" library_path ${library_path})
+ get_filename_component(base_name ${library_path} NAME)
+ file(TO_NATIVE_PATH ${library_path} source_path)
+ file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${base_name}" dest_path)
+ add_custom_command(OUTPUT "${base_name}"
+ COMMAND mklink /H "${dest_path}" "${source_path}"
+ DEPENDS ${library_path}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMENT "Creating hardlink to shiboken shared library ${base_name}")
+
+ # Fake target that depends on the previous one, but has special ALL keyword, which means
+ # it will always be executed.
+ add_custom_target("fake_${base_name}" ALL DEPENDS ${base_name})
+ endforeach()
+ # =========================================================================================
+ # !!! End of dubious section.
+ # =========================================================================================
+endif()
+
+# =============================================================================================
+# !!! (The section below is deployment related, so in a real world application you will want to
+# take care of this properly with some custom script or tool).
+# =============================================================================================
+# Install the library and the bindings module into the source folder near the main.py file, so
+# that the Python interpeter successfully imports the used module.
+install(TARGETS ${bindings_library} ${sample_library}
+ LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}
+ RUNTIME DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+# =============================================================================================
+# !!! End of dubious section.
+# =============================================================================================
diff --git a/examples/samplebinding/README.md b/examples/samplebinding/README.md
new file mode 100644
index 000000000..85e96ddbe
--- /dev/null
+++ b/examples/samplebinding/README.md
@@ -0,0 +1,223 @@
+# Sample bindings example
+
+This example showcases how to generate Python bindings for a
+non-Qt C++ library.
+
+The example defines a CMake project that builds two libraries:
+* `libuniverse` - a sample library with two C++ classes.
+* `Universe` - the generated Python extension module that contains
+ bindings to the library above.
+
+The project file is structured in such a way that a user can copy-paste
+in into their own project, and be able to build it with a minimal amount
+of modifications.
+
+## Description
+
+The libuniverse library declares two classes: `Icecream` and `Truck`.
+
+`Icecream` objects have a flavor, and an accessor for returning the
+flavor.
+
+`Truck` instances store a vector of `Icecream` objects, and have various
+methods for adding new flavors, printing available flavors, delivering
+icecream, etc.
+
+From a C++ perspective, `Icecream` instances are treated as
+**object types** (pointer semantics) because the class declares virtual
+methods.
+
+In contrast `Truck` does not define virtual methods and is treated as
+a **value type** (copy semantics).
+
+Because `Truck` is a value type and it stores a vector of `Icecream`
+pointers, the rule of three has to be taken into account (implement the
+copy constructor, assignment operator, destructor).
+
+And due to `Icecream` objects being copyable, the type has to define an
+implementation of the *clone()* method, to avoid type slicing issues.
+
+Both of these types and their methods will be exposed to Python by
+generating CPython code. The code is generated by **shiboken** and
+placed in separate ".cpp" files named after each C++ type. The code is
+then compiled and linked into a shared library. The shared library is a
+CPython extension module, which is loaded by the Python interpreter.
+
+Beacuse the C++ language has different semantics to Python, shiboken
+needs help in figuring out how to generate the bindings code. This is
+done by specifying a special XML file called a typesystem file.
+
+In the typesystem file you specify things like:
+ * which C++ primitive types should have bindings (int, bool, float)
+ * which C++ classes should have bindings (Icecream) and what kind of
+ semantics (value / object)
+ * Ownership rules (who deletes the C++ objects, C++ or Python)
+ * Code injection (for various special cases that shiboken doesn't know
+ about)
+ * Package name (name of package as imported from Python)
+
+In this example we declare `bool` and `std::string` as primitive types,
+`Icecream` as an object type, `Truck` as a value type,
+and the `clone()` and `addIcecreamFlavor(Icecream*)` need additional
+info about who owns the parameter objects when passing them across
+language boundaries (in this case C++ will delete the objects).
+
+After shiboken generates the C++ code and CMake makes an extension
+module from the code, the types can be accessed in Python simply by
+importing them using the original C++ names.
+
+```
+from Universe import Icecream, Truck
+```
+
+Constructing C++ wrapped objects is the same as in Python
+```
+icecream = Icecream("vanilla")
+truck = Truck()
+```
+
+
+And actual C++ constructors are mapped to the Python `__init__` method.
+```
+class VanillaChocolateIcecream(Icecream):
+ def __init__(self, flavor=""):
+ super(VanillaChocolateIcecream, self).__init__(flavor)
+```
+
+
+C++ methods can be accessed as regular Python methods using the C++
+names
+```
+truck.addIcecreamFlavor(icecream)
+```
+
+
+Inheritance works as with regular Python classes, and virtual C++
+methods can be overridden simply by definining a method with the same
+name as in the C++ class.
+```
+class VanillaChocolateIcecream(Icecream):
+ # ...
+ def getFlavor(self):
+ return "vanilla sprinked with chocolate"
+
+```
+
+
+The `main.py` script demonstrates usages of these types.
+
+The CMake project file contains many comments explaining all the build
+rules for those interested in the build process.
+
+## Building the project
+
+This example can only be built using **CMake**.
+The following requirements need to be met:
+
+* A PySide2 package is installed into the current active Python
+ environment (system or virtualenv)
+* A new enough version of CMake (**3.1+**).
+
+For Windows you will also need:
+* a Visual Studio environment to be active in your terminal
+* Correct visual studio architecture chosen (32 vs 64 bit)
+* Make sure that your Python intepreter and bindings project build
+ configuration is the same (all Release, which is more likely,
+ or all Debug).
+
+The build uses the `pyside2_config.py` file to configure the project
+using the current PySide2/Shiboken2 installation.
+
+### Using CMake
+
+You can build and run this example by executing the following commands
+(slightly adapted to your file system layout) in a terminal:
+
+On macOS/Linux:
+```bash
+cd ~/pyside-setup/examples/samplebinding
+mkdir build
+cd build
+cmake -H.. -B. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release
+make
+make install
+python ../main.py
+```
+
+On Windows:
+```bash
+cd C:\pyside-setup\examples\samplebinding
+mkdir build
+cd build
+cmake -H.. -B. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release
+# or if you have jom available
+# cmake -H.. -B. -G "NMake Makefiles JOM" -DCMAKE_BUILD_TYPE=Release
+nmake # or jom
+nmake install # or jom install
+python ..\main.py
+```
+
+#### Windows troubleshooting
+
+It is possible that **CMake** can pick up the wrong compiler
+for a different architecture, but it can be addressed explicitly
+using the -G option:
+
+```bash
+cmake -H.. -B. -G "Visual Studio 14 Win64"
+```
+
+If the `-G "Visual Studio 14 Win64"` option is used, a `sln` file
+will be generated, and can be used with `MSBuild`
+instead of `nmake/jom`.
+The easiest way to both build and install in this case, is to use
+the cmake executable:
+
+```bash
+cmake --build . --target install --config Release
+```
+
+Note that using the "NMake Makefiles JOM" generator is preferred to
+the MSBuild one, because the MSBuild one generates configs for both
+Debug and Release, and this might lead to building errors if you
+accidentally build the wrong config at least once.
+
+## Virtualenv Support
+
+If the python application is started from a terminal with an activated
+python virtual environment, that environment's packages will be used for
+the python module import process.
+In this case, make sure that the bindings were built while the
+`virtualenv` was active, so that the build system picks up the correct
+python shared library and PySide2 / shiboken package.
+
+## Linux Shared Libraries Notes
+
+For this example's purpose, we link against the absolute path of the
+dependent shared library `libshiboken` because the
+installation of the library is done via a wheel, and there is
+no clean solution to include symbolic links in a wheel package
+(so that passing -lshiboken to the linker would work).
+
+## Windows Notes
+
+The build config of the bindings (Debug or Release) should match
+the PySide2 build config, otherwise the application will not properly
+work.
+
+In practice this means the only supported configurations are:
+
+1. release config build of the bindings +
+ PySide2 `setup.py` without `--debug` flag + `python.exe` for the
+ PySide2 build process + `python36.dll` for the linked in shared
+ library.
+2. debug config build of the application +
+ PySide2 `setup.py` **with** `--debug` flag + `python_d.exe` for the
+ PySide2 build process + `python36_d.dll` for the linked in shared
+ library.
+
+This is necessary because all the shared libraries in question have to
+link to the same C++ runtime library (`msvcrt.dll` or `msvcrtd.dll`).
+To make the example as self-contained as possible, the shared libraries
+in use (`pyside2.dll`, `shiboken2.dll`) are hard-linked into the build
+folder of the application.
diff --git a/examples/samplebinding/bindings.h b/examples/samplebinding/bindings.h
new file mode 100644
index 000000000..ba42dc626
--- /dev/null
+++ b/examples/samplebinding/bindings.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * 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.
+** * Neither the name of The Qt Company Ltd 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
+** OWNER 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BINDINGS_H
+#define BINDINGS_H
+
+#include "icecream.h"
+#include "truck.h"
+
+#endif // BINDINGS_H
diff --git a/examples/samplebinding/bindings.xml b/examples/samplebinding/bindings.xml
new file mode 100644
index 000000000..f08243694
--- /dev/null
+++ b/examples/samplebinding/bindings.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<!--
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * 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.
+** * Neither the name of The Qt Company Ltd 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
+** OWNER 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+-->
+<typesystem package="Universe">
+
+ <primitive-type name="bool"/>
+ <primitive-type name="std::string"/>
+
+ <object-type name="Icecream">
+ <!-- By default the ownership of an object created in Python is tied
+ to the Python name pointing to it. In order for the underlying
+ C++ object not to get deleted when the Python name goes out of
+ scope, we have to transfer ownership to C++.
+ -->
+ <modify-function signature="clone()">
+ <modify-argument index="0">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ </object-type>
+
+ <value-type name="Truck">
+ <!-- Same ownership caveat applies here. -->
+ <modify-function signature="addIcecreamFlavor(Icecream*)">
+ <modify-argument index="1">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+
+</typesystem>
diff --git a/examples/samplebinding/icecream.cpp b/examples/samplebinding/icecream.cpp
new file mode 100644
index 000000000..8d40302da
--- /dev/null
+++ b/examples/samplebinding/icecream.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * 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.
+** * Neither the name of The Qt Company Ltd 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
+** OWNER 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "icecream.h"
+
+Icecream::Icecream(const std::string &flavor) : m_flavor(flavor) {}
+
+Icecream::~Icecream() {}
+
+const std::string Icecream::getFlavor()
+{
+ return m_flavor;
+}
+
+Icecream *Icecream::clone()
+{
+ return new Icecream(*this);
+}
diff --git a/examples/samplebinding/icecream.h b/examples/samplebinding/icecream.h
new file mode 100644
index 000000000..1997fdc49
--- /dev/null
+++ b/examples/samplebinding/icecream.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * 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.
+** * Neither the name of The Qt Company Ltd 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
+** OWNER 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ICECREAM_H
+#define ICECREAM_H
+
+#include <string>
+
+#include "macros.h"
+
+class BINDINGS_API Icecream
+{
+public:
+ Icecream(const std::string &flavor);
+ virtual Icecream *clone();
+ virtual ~Icecream();
+ virtual const std::string getFlavor();
+
+private:
+ std::string m_flavor;
+};
+
+
+#endif // ICECREAM_H
diff --git a/examples/samplebinding/macros.h b/examples/samplebinding/macros.h
new file mode 100644
index 000000000..71b27c398
--- /dev/null
+++ b/examples/samplebinding/macros.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * 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.
+** * Neither the name of The Qt Company Ltd 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
+** OWNER 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MACROS_H
+#define MACROS_H
+
+#if defined _WIN32 || defined __CYGWIN__
+ // Export symbols when creating .dll and .lib, and import them when using .lib.
+ #if BINDINGS_BUILD
+ #define BINDINGS_API __declspec(dllexport)
+ #else
+ #define BINDINGS_API __declspec(dllimport)
+ #endif
+ // Disable warnings about exporting STL types being a bad idea. Don't use this in production
+ // code.
+ #pragma warning( disable : 4251 )
+#else
+ #define BINDINGS_API
+#endif
+
+#endif // MACROS_H
diff --git a/examples/samplebinding/main.py b/examples/samplebinding/main.py
new file mode 100644
index 000000000..b9487f7ba
--- /dev/null
+++ b/examples/samplebinding/main.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * 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.
+## * Neither the name of The Qt Company Ltd 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
+## OWNER 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."
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+from __future__ import print_function
+
+"""An example showcasing how to use bindings for a custom non-Qt C++ library"""
+
+from Universe import Icecream, Truck
+
+class VanillaChocolateIcecream(Icecream):
+ def __init__(self, flavor=""):
+ super(VanillaChocolateIcecream, self).__init__(flavor)
+
+ def clone(self):
+ return VanillaChocolateIcecream(self.getFlavor())
+
+ def getFlavor(self):
+ return "vanilla sprinked with chocolate"
+
+class VanillaChocolateCherryIcecream(VanillaChocolateIcecream):
+ def __init__(self, flavor=""):
+ super(VanillaChocolateIcecream, self).__init__(flavor)
+
+ def clone(self):
+ return VanillaChocolateCherryIcecream(self.getFlavor())
+
+ def getFlavor(self):
+ base_flavor = super(VanillaChocolateCherryIcecream, self).getFlavor()
+ return base_flavor + " and a cherry"
+
+if __name__ == '__main__':
+ leave_on_destruction = True
+ truck = Truck(leave_on_destruction)
+
+ flavors = ["vanilla", "chocolate", "strawberry"]
+ for f in flavors:
+ icecream = Icecream(f)
+ truck.addIcecreamFlavor(icecream)
+
+ truck.addIcecreamFlavor(VanillaChocolateIcecream())
+ truck.addIcecreamFlavor(VanillaChocolateCherryIcecream())
+
+ truck.arrive()
+ truck.printAvailableFlavors()
+ result = truck.deliver()
+
+ if result:
+ print("All the kids got some icecream!")
+ else:
+ print("Aww, someone didn't get the flavor they wanted...")
+
+ if not result:
+ special_truck = Truck(truck)
+ del truck
+
+ print("")
+ special_truck.setArrivalMessage("A new SPECIAL icecream truck has arrived!\n")
+ special_truck.arrive()
+ special_truck.addIcecreamFlavor(Icecream("SPECIAL *magical* icecream"))
+ special_truck.printAvailableFlavors()
+ special_truck.deliver()
+ print("Now everyone got the flavor they wanted!")
+ special_truck.leave()
diff --git a/examples/samplebinding/truck.cpp b/examples/samplebinding/truck.cpp
new file mode 100644
index 000000000..6e24bdc87
--- /dev/null
+++ b/examples/samplebinding/truck.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * 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.
+** * Neither the name of The Qt Company Ltd 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
+** OWNER 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <iostream>
+#include <random>
+
+#include "truck.h"
+
+Truck::Truck(bool leaveOnDestruction) : m_leaveOnDestruction(leaveOnDestruction) {}
+
+Truck::Truck(const Truck &other)
+{
+ for (size_t i = 0; i < other.m_flavors.size(); ++i) {
+ addIcecreamFlavor(other.m_flavors[i]->clone());
+ }
+}
+
+Truck &Truck::operator=(const Truck &other)
+{
+ if (this != &other) {
+ clearFlavors();
+ for (size_t i = 0; i < other.m_flavors.size(); ++i) {
+ addIcecreamFlavor(other.m_flavors[i]->clone());
+ }
+ }
+ return *this;
+}
+
+Truck::~Truck()
+{
+ if (m_leaveOnDestruction)
+ leave();
+ clearFlavors();
+}
+
+void Truck::addIcecreamFlavor(Icecream *icecream)
+{
+ m_flavors.push_back(icecream);
+}
+
+void Truck::printAvailableFlavors() const
+{
+ std::cout << "It sells the following flavors: \n";
+ for (size_t i = 0; i < m_flavors.size(); ++ i) {
+ std::cout << " * " << m_flavors[i]->getFlavor() << '\n';
+ }
+ std::cout << '\n';
+}
+
+void Truck::arrive() const
+{
+ std::cout << m_arrivalMessage;
+}
+
+void Truck::leave() const
+{
+ std::cout << "The truck left the neighborhood.\n";
+}
+
+void Truck::setLeaveOnDestruction(bool value)
+{
+ m_leaveOnDestruction = value;
+}
+
+void Truck::setArrivalMessage(const std::string &message)
+{
+ m_arrivalMessage = message;
+}
+
+bool Truck::deliver() const
+{
+ std::random_device rd;
+ std::mt19937 mt(rd());
+ std::uniform_int_distribution<int> dist(1, 2);
+
+ std::cout << "The truck started delivering icecream to all the kids in the neighborhood.\n";
+ bool result = false;
+
+ if (dist(mt) == 2)
+ result = true;
+
+ return result;
+}
+
+void Truck::clearFlavors()
+{
+ for (size_t i = 0; i < m_flavors.size(); ++i) {
+ delete m_flavors[i];
+ }
+ m_flavors.clear();
+}
diff --git a/examples/samplebinding/truck.h b/examples/samplebinding/truck.h
new file mode 100644
index 000000000..02e304a82
--- /dev/null
+++ b/examples/samplebinding/truck.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * 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.
+** * Neither the name of The Qt Company Ltd 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
+** OWNER 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TRUCK_H
+#define TRUCK_H
+
+#include <vector>
+
+#include "icecream.h"
+#include "macros.h"
+
+class BINDINGS_API Truck {
+public:
+ Truck(bool leaveOnDestruction = false);
+ Truck(const Truck &other);
+ Truck& operator=(const Truck &other);
+ ~Truck();
+
+ void addIcecreamFlavor(Icecream *icecream);
+ void printAvailableFlavors() const;
+
+ bool deliver() const;
+ void arrive() const;
+ void leave() const;
+
+ void setLeaveOnDestruction(bool value);
+ void setArrivalMessage(const std::string &message);
+
+private:
+ void clearFlavors();
+
+ bool m_leaveOnDestruction = false;
+ std::string m_arrivalMessage = "A new icecream truck has arrived!\n";
+ std::vector<Icecream *> m_flavors;
+};
+
+#endif // TRUCK_H
diff --git a/examples/scriptableapplication/CMakeLists.txt b/examples/scriptableapplication/CMakeLists.txt
index 7e57a291b..4119b6756 100644
--- a/examples/scriptableapplication/CMakeLists.txt
+++ b/examples/scriptableapplication/CMakeLists.txt
@@ -23,7 +23,7 @@ macro(pyside2_config option output_var)
endif()
execute_process(
- COMMAND python "${CMAKE_SOURCE_DIR}/pyside2_config.py" ${option}
+ COMMAND python "${CMAKE_SOURCE_DIR}/../utils/pyside2_config.py" ${option}
OUTPUT_VARIABLE ${output_var}
OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -35,19 +35,19 @@ macro(pyside2_config option output_var)
endif()
endmacro()
-# Get relevant general paths, include paths and linker flags.
+# Query for the PySide2 path, Python path, include paths and linker flags.
pyside2_config(--pyside2 PYSIDE2_PATH)
+pyside2_config(--python-include PYTHON_INCLUDE_DIR)
+pyside2_config(--pyside2-include PYSIDE2_INCLUDE_DIR 1)
+pyside2_config(--pyside2-shared-libraries-cmake PYSIDE2_SHARED_LIBRARIES 0)
+pyside2_config(--python-link-cmake PYTHON_LINKING_DATA 0)
+
set(SHIBOKEN_PATH "${PYSIDE2_PATH}/shiboken2${CMAKE_EXECUTABLE_SUFFIX}")
if(NOT EXISTS ${SHIBOKEN_PATH})
message(FATAL_ERROR "Shiboken executable not found at path: ${SHIBOKEN_PATH}")
endif()
-pyside2_config(--pyside2 PYSIDE2_DIR)
-pyside2_config(--python-include PYTHON_INCLUDE_DIR)
-pyside2_config(--pyside2-include PYSIDE2_INCLUDE_DIR 1)
-pyside2_config(--pyside2-shared-libraries-cmake PYSIDE2_SHARED_LIBRARIES 0)
-pyside2_config(--python-link-cmake PYTHON_LINKING_DATA 0)
# Get all relevant Qt include dirs, to pass them on to shiboken.
get_property(QT_CORE_INCLUDE_DIRS TARGET Qt5::Core PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
@@ -122,7 +122,7 @@ endforeach()
# Enable rpaths so that the example can be executed from the build dir.
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
-set(CMAKE_INSTALL_RPATH ${PYSIDE2_DIR})
+set(CMAKE_INSTALL_RPATH ${PYSIDE2_PATH})
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# =============================================================================================
# !!! End of dubious section.
diff --git a/examples/scriptableapplication/pyside2.pri b/examples/scriptableapplication/pyside2.pri
index 59f7fd983..17be4392f 100644
--- a/examples/scriptableapplication/pyside2.pri
+++ b/examples/scriptableapplication/pyside2.pri
@@ -1,19 +1,21 @@
-PYSIDE2 = $$system(python $$PWD/pyside2_config.py --pyside2)
+PYSIDE_CONFIG = $$PWD/../utils/pyside2_config.py
+
+PYSIDE2 = $$system(python $$PYSIDE_CONFIG --pyside2)
isEmpty(PYSIDE2): error(Unable to locate the PySide2 package location)
-PYTHON_INCLUDE = $$system(python $$PWD/pyside2_config.py --python-include)
+PYTHON_INCLUDE = $$system(python $$PYSIDE_CONFIG --python-include)
isEmpty(PYTHON_INCLUDE): error(Unable to locate the Python include headers directory)
-PYTHON_LFLAGS = $$system(python $$PWD/pyside2_config.py --python-link)
+PYTHON_LFLAGS = $$system(python $$PYSIDE_CONFIG --python-link)
isEmpty(PYTHON_LFLAGS): error(Unable to locate the Python library for linking)
-PYSIDE2_INCLUDE = $$system(python $$PWD/pyside2_config.py --pyside2-include)
+PYSIDE2_INCLUDE = $$system(python $$PYSIDE_CONFIG --pyside2-include)
isEmpty(PYSIDE2_INCLUDE): error(Unable to locate the PySide2 include headers directory)
-PYSIDE2_LFLAGS = $$system(python $$PWD/pyside2_config.py --pyside2-link)
+PYSIDE2_LFLAGS = $$system(python $$PYSIDE_CONFIG --pyside2-link)
isEmpty(PYSIDE2_LFLAGS): error(Unable to locate the PySide2 libraries for linking)
-PYSIDE2_SHARED_LIBRARIES = $$system(python $$PWD/pyside2_config.py --pyside2-shared-libraries)
+PYSIDE2_SHARED_LIBRARIES = $$system(python $$PYSIDE_CONFIG --pyside2-shared-libraries)
isEmpty(PYSIDE2_SHARED_LIBRARIES): error(Unable to locate the used PySide2 shared libraries)
INCLUDEPATH += "$$PYTHON_INCLUDE" $$PYSIDE2_INCLUDE
diff --git a/examples/scriptableapplication/pyside2_config.py b/examples/utils/pyside2_config.py
index ce9c707c1..298d40d5b 100644
--- a/examples/scriptableapplication/pyside2_config.py
+++ b/examples/utils/pyside2_config.py
@@ -72,10 +72,10 @@ def sharedLibraryGlobPattern():
glob = '*.' + sharedLibrarySuffix()
return glob if sys.platform == 'win32' else 'lib' + glob
-def filterPySide2SharedLibraries(list):
+def filterPySide2SharedLibraries(list, only_shiboken=False):
def predicate(item):
basename = os.path.basename(item)
- if 'shiboken' in basename or 'pyside2' in basename:
+ if 'shiboken' in basename or ('pyside2' in basename and not only_shiboken):
return True
return False
result = [item for item in list if predicate(item)]
@@ -165,11 +165,16 @@ def pythonLinkData():
return flags
-def pyside2Include():
+def pyside2Include(only_shiboken=False):
pySide2 = findPySide2()
if pySide2 is None:
return None
- return "{0}/include/PySide2 {0}/include/shiboken2".format(pySide2)
+
+ includes = "{0}/include/shiboken2".format(pySide2)
+ if not only_shiboken:
+ includes = includes + " {0}/include/PySide2".format(pySide2)
+
+ return includes
def pyside2Link():
pySide2 = findPySide2()
@@ -182,13 +187,13 @@ def pyside2Link():
link += linkOption(lib)
return link
-def pyside2SharedLibrariesData():
+def pyside2SharedLibrariesData(only_shiboken=False):
pySide2 = findPySide2()
if pySide2 is None:
return None
glob_result = glob.glob(os.path.join(pySide2, sharedLibraryGlobPattern()))
- filtered_libs = filterPySide2SharedLibraries(glob_result)
+ filtered_libs = filterPySide2SharedLibraries(glob_result, only_shiboken)
libs = []
if sys.platform == 'win32':
for lib in filtered_libs:
@@ -218,8 +223,8 @@ def pyside2SharedLibraries():
libs_string += lib + ' '
return libs_string
-def pyside2SharedLibrariesCmake():
- libs = pyside2SharedLibrariesData()
+def pyside2SharedLibrariesCmake(only_shiboken=False):
+ libs = pyside2SharedLibrariesData(only_shiboken)
result = ';'.join(libs)
return result
@@ -248,6 +253,12 @@ if option == '--pyside2-link' or option == '-a':
print(l)
+if option == '--shiboken-include' or option == '-a':
+ i = pyside2Include(only_shiboken=True)
+ if i is None:
+ sys.exit(pyside2_error)
+ print(i)
+
if option == '--pyside2-include' or option == '-a':
i = pyside2Include()
if i is None:
@@ -283,3 +294,9 @@ if option == '--pyside2-shared-libraries-cmake' or option == '-a':
if l is None:
sys.exit(pyside2_libs_error)
print(l)
+
+if option == '--shiboken-shared-libraries-cmake' or option == '-a':
+ l = pyside2SharedLibrariesCmake(only_shiboken=True)
+ if l is None:
+ sys.exit(pyside2_libs_error)
+ print(l)