aboutsummaryrefslogtreecommitdiffstats
path: root/examples/samplebinding
diff options
context:
space:
mode:
Diffstat (limited to 'examples/samplebinding')
-rw-r--r--examples/samplebinding/CMakeLists.txt67
-rw-r--r--examples/samplebinding/README.md236
-rw-r--r--examples/samplebinding/bindings.h51
-rw-r--r--examples/samplebinding/bindings.xml54
-rw-r--r--examples/samplebinding/doc/bindings.h.rstinc2
-rw-r--r--examples/samplebinding/doc/bindings.xml.rstinc31
-rw-r--r--examples/samplebinding/doc/samplebinding.pyproject11
-rw-r--r--examples/samplebinding/doc/samplebinding.rst292
-rw-r--r--examples/samplebinding/icecream.cpp63
-rw-r--r--examples/samplebinding/icecream.h61
-rw-r--r--examples/samplebinding/macros.h51
-rw-r--r--examples/samplebinding/main.py53
-rw-r--r--examples/samplebinding/truck.cpp88
-rw-r--r--examples/samplebinding/truck.h70
14 files changed, 448 insertions, 682 deletions
diff --git a/examples/samplebinding/CMakeLists.txt b/examples/samplebinding/CMakeLists.txt
index f7651e04f..4807904c1 100644
--- a/examples/samplebinding/CMakeLists.txt
+++ b/examples/samplebinding/CMakeLists.txt
@@ -1,5 +1,8 @@
-cmake_minimum_required(VERSION 3.16)
-cmake_policy(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
+cmake_policy(VERSION 3.18)
# Enable policy to not use RPATH settings for install_name on macOS.
if(POLICY CMP0068)
@@ -11,8 +14,8 @@ project(SampleBinding)
# ================================ General configuration ======================================
-# Set CPP standard to C++11 minimum.
-set(CMAKE_CXX_STANDARD 11)
+# Set CPP standard to C++17 minimum.
+set(CMAKE_CXX_STANDARD 17)
# The sample library for which we will create bindings. You can change the name to something
# relevant for your project.
@@ -42,13 +45,27 @@ set(generated_sources
# ================================== Shiboken detection ======================================
# Use provided python interpreter if given.
if(NOT python_interpreter)
- find_program(python_interpreter "python")
+ if(WIN32 AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
+ find_program(python_interpreter "python_d")
+ if(NOT python_interpreter)
+ message(FATAL_ERROR
+ "A debug Python interpreter could not be found, which is a requirement when "
+ "building this example in a debug configuration. Make sure python_d.exe is in "
+ "PATH.")
+ endif()
+ else()
+ find_program(python_interpreter "python")
+ if(NOT python_interpreter)
+ message(FATAL_ERROR
+ "No Python interpreter could be found. Make sure python is in PATH.")
+ endif()
+ endif()
endif()
message(STATUS "Using python interpreter: ${python_interpreter}")
# 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)
+# Uses the not entirely supported utils/pyside_config.py file.
+macro(pyside_config option output_var)
if(${ARGC} GREATER 2)
set(is_list ${ARGV2})
else()
@@ -56,13 +73,13 @@ macro(pyside2_config option output_var)
endif()
execute_process(
- COMMAND ${python_interpreter} "${CMAKE_SOURCE_DIR}/../utils/pyside2_config.py"
+ COMMAND ${python_interpreter} "${CMAKE_SOURCE_DIR}/../utils/pyside_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.")
+ message(FATAL_ERROR "Error: Calling pyside_config.py ${option} returned no output.")
endif()
if(is_list)
string (REPLACE " " ";" ${output_var} "${${output_var}}")
@@ -70,14 +87,14 @@ macro(pyside2_config option output_var)
endmacro()
# Query for the shiboken generator path, Python path, include paths and linker flags.
-pyside2_config(--shiboken2-module-path shiboken2_module_path)
-pyside2_config(--shiboken2-generator-path shiboken2_generator_path)
-pyside2_config(--python-include-path python_include_dir)
-pyside2_config(--shiboken2-generator-include-path shiboken_include_dir 1)
-pyside2_config(--shiboken2-module-shared-libraries-cmake shiboken_shared_libraries 0)
-pyside2_config(--python-link-flags-cmake python_linking_data 0)
-
-set(shiboken_path "${shiboken2_generator_path}/shiboken2${CMAKE_EXECUTABLE_SUFFIX}")
+pyside_config(--shiboken-module-path shiboken_module_path)
+pyside_config(--shiboken-generator-path shiboken_generator_path)
+pyside_config(--python-include-path python_include_dir)
+pyside_config(--shiboken-generator-include-path shiboken_include_dir 1)
+pyside_config(--shiboken-module-shared-libraries-cmake shiboken_shared_libraries 0)
+pyside_config(--python-link-flags-cmake python_linking_data 0)
+
+set(shiboken_path "${shiboken_generator_path}/shiboken6${CMAKE_EXECUTABLE_SUFFIX}")
if(NOT EXISTS ${shiboken_path})
message(FATAL_ERROR "Shiboken executable not found at path: ${shiboken_path}")
endif()
@@ -93,7 +110,7 @@ endif()
# 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 ${shiboken2_module_path} ${CMAKE_CURRENT_SOURCE_DIR})
+set(CMAKE_INSTALL_RPATH ${shiboken_module_path} ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# =============================================================================================
# !!! End of dubious section.
@@ -118,7 +135,7 @@ target_compile_definitions(${sample_library} PRIVATE BINDINGS_BUILD)
# 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
+ --enable-return-value-heuristic --use-isnull-as-nb-bool
--avoid-protected-hack
-I${CMAKE_SOURCE_DIR}
-T${CMAKE_SOURCE_DIR}
@@ -159,7 +176,11 @@ 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")
+ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
+ set_property(TARGET ${bindings_library} PROPERTY SUFFIX "_d.pyd")
+ else()
+ set_property(TARGET ${bindings_library} PROPERTY SUFFIX ".pyd")
+ endif()
endif()
# Make sure the linker doesn't complain about not finding Python symbols on macOS.
@@ -191,7 +212,7 @@ if(WIN32)
# 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_versions_list 3 36 37 38 39)
set(python_additional_link_flags "")
foreach(ver ${python_versions_list})
set(python_additional_link_flags
@@ -204,7 +225,7 @@ if(WIN32)
PROPERTIES LINK_FLAGS "${python_additional_link_flags}")
# Compile a list of shiboken shared libraries to be installed, so that
- # the user doesn't have to set the PATH manually to point to the PySide2 package.
+ # the user doesn't have to set the PATH manually to point to the PySide6 package.
foreach(library_path ${shiboken_shared_libraries})
string(REGEX REPLACE ".lib$" ".dll" library_path ${library_path})
file(TO_CMAKE_PATH ${library_path} library_path)
@@ -224,7 +245,7 @@ endif()
install(TARGETS ${bindings_library} ${sample_library}
LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}
RUNTIME DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}
- )
+ )
install(FILES ${windows_shiboken_shared_libraries} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR})
# =============================================================================================
# !!! End of dubious section.
diff --git a/examples/samplebinding/README.md b/examples/samplebinding/README.md
deleted file mode 100644
index e84d1eff4..000000000
--- a/examples/samplebinding/README.md
+++ /dev/null
@@ -1,236 +0,0 @@
-# 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).
-
-The `Truck` has getters and setters for the string `arrivalMessage`.
-In the type system file, we declare this to be a property in Python:
-
-```
-<property type="std::string" name="arrivalMessage" get="getArrivalMessage" set="setArrivalMessage"/>
-```
-
-It can then be used in a more pythonic way:
-
-```
-special_truck.arrivalMessage = "A new SPECIAL icecream truck has arrived!\n"
-```
-
-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
index ba42dc626..36f0b86be 100644
--- a/examples/samplebinding/bindings.h
+++ b/examples/samplebinding/bindings.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef BINDINGS_H
#define BINDINGS_H
diff --git a/examples/samplebinding/bindings.xml b/examples/samplebinding/bindings.xml
index 9be9f1afa..fe5b4e5e2 100644
--- a/examples/samplebinding/bindings.xml
+++ b/examples/samplebinding/bindings.xml
@@ -1,60 +1,10 @@
<?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$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-->
<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
diff --git a/examples/samplebinding/doc/bindings.h.rstinc b/examples/samplebinding/doc/bindings.h.rstinc
new file mode 100644
index 000000000..e2a0b6fef
--- /dev/null
+++ b/examples/samplebinding/doc/bindings.h.rstinc
@@ -0,0 +1,2 @@
+The Shiboken generator needs a header file that includes
+the types we are interested in:
diff --git a/examples/samplebinding/doc/bindings.xml.rstinc b/examples/samplebinding/doc/bindings.xml.rstinc
new file mode 100644
index 000000000..60b9b1a48
--- /dev/null
+++ b/examples/samplebinding/doc/bindings.xml.rstinc
@@ -0,0 +1,31 @@
+Shiboken requires an XML-based typesystem file that defines the
+relationship between C++ and Python types.
+
+It declares the two aforementioned classes. One of them as an
+“object-type” and the other as a “value-type”. The main difference is that
+object-types are passed around in generated code as pointers, whereas
+value-types are copied (value semantics).
+
+By specifying the names of these classes in the typesystem file, Shiboken
+automatically tries to generate bindings for all methods of those
+classes. You need not mention all the methods manually in the XML file, unless
+you want to modify them.
+
+**Object ownership rules**
+
+Shiboken doesn't know if Python or C++ are responsible for freeing the C++
+objects that were allocated in the Python code, and assuming this might lead to
+errors. There can be cases where Python should release the C++ memory when the
+reference count of the Python object becomes zero, but it should never delete
+the underlying C++ object just from assuming that it will not be deleted by
+underlying C++ library, or if it's maybe parented to another object (like
+QWidgets).
+
+In our case, the :code:`clone()` method is only called inside the C++ library,
+and we assume that the C++ code takes care of releasing the cloned object.
+
+As for :code:`addIcecreamFlavor()`, we know that a :code:`Truck` owns the
+:code:`Icecream` object, and will remove it once the :code:`Truck` is
+destroyed. That's why the ownership is set to “c++” in the typesystem file,
+so that the C++ objects are not deleted when the corresponding Python names
+go out of scope.
diff --git a/examples/samplebinding/doc/samplebinding.pyproject b/examples/samplebinding/doc/samplebinding.pyproject
new file mode 100644
index 000000000..b0786355f
--- /dev/null
+++ b/examples/samplebinding/doc/samplebinding.pyproject
@@ -0,0 +1,11 @@
+{
+ "files": ["../bindings.h",
+ "../bindings.xml",
+ "../icecream.cpp",
+ "../icecream.h",
+ "../macros.h",
+ "../main.py",
+ "../truck.cpp",
+ "../truck.h",
+ "../CMakeLists.txt"]
+}
diff --git a/examples/samplebinding/doc/samplebinding.rst b/examples/samplebinding/doc/samplebinding.rst
new file mode 100644
index 000000000..51b6b4c20
--- /dev/null
+++ b/examples/samplebinding/doc/samplebinding.rst
@@ -0,0 +1,292 @@
+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 five has to be taken into account (implement the
+copy constructor, assignment operator, move constructor, move assignment
+operator and 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++ classes should have bindings (Icecream, Truck) and with 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 ``Icecream`` as an object type and ``Truck``
+as a value type. 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).
+
+The ``Truck`` has getters and setters for the string ``arrivalMessage``.
+In the type system file, we declare this to be a property in Python:
+
+.. code-block:: xml
+
+ <property type="std::string" name="arrivalMessage" get="getArrivalMessage" set="setArrivalMessage"/>
+
+
+It can then be used in a more pythonic way:
+
+.. code-block:: python
+
+ special_truck.arrivalMessage = "A new SPECIAL icecream truck has arrived!\n"
+
+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.
+
+.. code-block:: python
+
+ from Universe import Icecream, Truck
+
+
+Constructing C++ wrapped objects is the same as in Python
+
+.. code-block:: python
+
+ icecream = Icecream("vanilla")
+ truck = Truck()
+
+
+And actual C++ constructors are mapped to the Python `__init__` method.
+
+.. code-block:: python
+
+ class VanillaChocolateIcecream(Icecream):
+ def __init__(self, flavor=""):
+ super().__init__(flavor)
+
+
+C++ methods can be accessed as regular Python methods using the C++
+names
+
+.. code-block:: python
+
+ 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.
+
+.. code-block:: python
+
+ 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 PySide package is installed into the current active Python
+ environment (system or virtualenv)
+
+* A new enough version of CMake (3.16+).
+
+* ninja
+
+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 ``pyside_config.py`` file to configure the project
+using the current PySide/Shiboken 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:
+
+Run CMake on macOS/Linux:
+
+.. code-block:: bash
+
+ cd ~/pyside-setup/examples/samplebinding
+ mkdir build
+ cd build
+ cmake .. -B. -G Ninja -DCMAKE_BUILD_TYPE=Release
+
+Run CMake on Windows:
+
+.. code-block:: bash
+
+ cd C:\pyside-setup\examples\samplebinding
+ mkdir build
+ cd build
+ cmake .. -B. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=cl.exe
+
+To build:
+
+.. code-block:: bash
+ ninja
+ ninja install
+ cd ..
+
+Use the Python module
++++++++++++++++++++++
+
+The final example can then be run by:
+
+.. code-block:: bash
+
+ python main.py
+
+In the ``main.py`` script, two types are derived from :code:`Icecream` for
+different “flavors” after importing the classes from the :code:`Universe`
+module. Then, a :code:`truck` is created to deliver some regular flavored
+Icecreams and two special ones.
+
+If the delivery fails, a new :code:`truck` is created with the old flavors
+copied over, and a new *magical* flavor that will surely satisfy all customers.
+
+Try running it to see if the ice creams are delivered.
+
+Windows troubleshooting
++++++++++++++++++++++++
+
+It is possible that ``CMake`` can pick up the wrong compiler
+for a different architecture, but it can be addressed explicitly
+by setting the ``CC`` environment variable:
+
+.. code-block:: bash
+
+ set CC=cl
+
+passing the compiler on the command line:
+
+.. code-block:: bash
+
+ cmake -S.. -B. -DCMAKE_C_COMPILER=cl.exe -DCMAKE_CXX_COMPILER=cl.exe
+
+or by using the -G option:
+
+.. code-block:: bash
+
+ cmake -S.. -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 ``ninja``.
+The easiest way to both build and install in this case, is to use
+the cmake executable:
+
+.. code-block:: bash
+
+ cmake --build . --target install --config Release
+
+Note that using the ``"Ninja"`` 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 PySide6 / 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 PySide build config, otherwise the application will not properly
+work.
+
+In practice this means the only supported configurations are:
+
+#. release config build of the bindings +
+ PySide ``setup.py`` without ``--debug`` flag + ``python.exe`` for the
+ PySide build process + ``python39.dll`` for the linked in shared
+ library.
+
+#. debug config build of the application +
+ PySide ``setup.py`` *with* ``--debug`` flag + ``python_d.exe`` for the
+ PySide build process + ``python39_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 (``pyside6.dll``, ``shiboken6.dll``) are hard-linked into the build
+folder of the application.
diff --git a/examples/samplebinding/icecream.cpp b/examples/samplebinding/icecream.cpp
index 8d40302da..4a81bd08b 100644
--- a/examples/samplebinding/icecream.cpp
+++ b/examples/samplebinding/icecream.cpp
@@ -1,60 +1,15 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "icecream.h"
+#include <iostream>
+
Icecream::Icecream(const std::string &flavor) : m_flavor(flavor) {}
-Icecream::~Icecream() {}
+Icecream::~Icecream() = default;
-const std::string Icecream::getFlavor()
+std::string Icecream::getFlavor() const
{
return m_flavor;
}
@@ -63,3 +18,9 @@ Icecream *Icecream::clone()
{
return new Icecream(*this);
}
+
+std::ostream &operator<<(std::ostream &str, const Icecream &i)
+{
+ str << i.getFlavor();
+ return str;
+}
diff --git a/examples/samplebinding/icecream.h b/examples/samplebinding/icecream.h
index 1997fdc49..7d5e97d38 100644
--- a/examples/samplebinding/icecream.h
+++ b/examples/samplebinding/icecream.h
@@ -1,71 +1,26 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef ICECREAM_H
#define ICECREAM_H
-#include <string>
-
#include "macros.h"
+#include <iosfwd>
+#include <string>
+
class BINDINGS_API Icecream
{
public:
- Icecream(const std::string &flavor);
+ explicit Icecream(const std::string &flavor);
virtual Icecream *clone();
virtual ~Icecream();
- virtual const std::string getFlavor();
+ virtual std::string getFlavor() const;
private:
std::string m_flavor;
};
+std::ostream &operator<<(std::ostream &str, const Icecream &i);
#endif // ICECREAM_H
diff --git a/examples/samplebinding/macros.h b/examples/samplebinding/macros.h
index 71b27c398..af1874fa4 100644
--- a/examples/samplebinding/macros.h
+++ b/examples/samplebinding/macros.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MACROS_H
#define MACROS_H
diff --git a/examples/samplebinding/main.py b/examples/samplebinding/main.py
index dc727c5d8..cb9f116ee 100644
--- a/examples/samplebinding/main.py
+++ b/examples/samplebinding/main.py
@@ -1,53 +1,14 @@
-
-############################################################################
-##
-## 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
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
"""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)
+ super().__init__(flavor)
def clone(self):
return VanillaChocolateIcecream(self.getFlavor())
@@ -55,16 +16,18 @@ class VanillaChocolateIcecream(Icecream):
def getFlavor(self):
return "vanilla sprinked with chocolate"
+
class VanillaChocolateCherryIcecream(VanillaChocolateIcecream):
def __init__(self, flavor=""):
- super(VanillaChocolateIcecream, self).__init__(flavor)
+ super().__init__(flavor)
def clone(self):
return VanillaChocolateCherryIcecream(self.getFlavor())
def getFlavor(self):
base_flavor = super(VanillaChocolateCherryIcecream, self).getFlavor()
- return base_flavor + " and a cherry"
+ return f"{base_flavor} and a cherry"
+
if __name__ == '__main__':
leave_on_destruction = True
diff --git a/examples/samplebinding/truck.cpp b/examples/samplebinding/truck.cpp
index 056abfcd6..819d2b1a0 100644
--- a/examples/samplebinding/truck.cpp
+++ b/examples/samplebinding/truck.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <iostream>
#include <random>
@@ -57,40 +10,38 @@ 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());
- }
+ assign(other);
}
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());
- }
+ m_flavors.clear();
+ assign(other);
}
return *this;
}
+Truck::Truck(Truck &&other) = default;
+
+Truck& Truck::operator=(Truck &&other) = default;
+
Truck::~Truck()
{
if (m_leaveOnDestruction)
leave();
- clearFlavors();
}
void Truck::addIcecreamFlavor(Icecream *icecream)
{
- m_flavors.push_back(icecream);
+ m_flavors.push_back(IcecreamPtr(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';
- }
+ for (const auto &flavor : m_flavors)
+ std::cout << " * " << *flavor << '\n';
std::cout << '\n';
}
@@ -119,6 +70,13 @@ std::string Truck::getArrivalMessage() const
return m_arrivalMessage;
}
+void Truck::assign(const Truck &other)
+{
+ m_flavors.reserve(other.m_flavors.size());
+ for (const auto &f : other.m_flavors)
+ m_flavors.push_back(IcecreamPtr(f->clone()));
+}
+
bool Truck::deliver() const
{
std::random_device rd;
@@ -133,11 +91,3 @@ bool Truck::deliver() const
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
index 3f213f9ac..f7afd1290 100644
--- a/examples/samplebinding/truck.h
+++ b/examples/samplebinding/truck.h
@@ -1,66 +1,24 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef TRUCK_H
#define TRUCK_H
-#include <vector>
-
#include "icecream.h"
#include "macros.h"
-class BINDINGS_API Truck {
+#include <memory>
+#include <vector>
+
+class BINDINGS_API Truck
+{
public:
- Truck(bool leaveOnDestruction = false);
+ explicit Truck(bool leaveOnDestruction = false);
Truck(const Truck &other);
Truck& operator=(const Truck &other);
+ Truck(Truck &&other);
+ Truck& operator=(Truck &&other);
+
~Truck();
void addIcecreamFlavor(Icecream *icecream);
@@ -76,11 +34,13 @@ public:
std::string getArrivalMessage() const;
private:
- void clearFlavors();
+ using IcecreamPtr = std::shared_ptr<Icecream>;
+
+ void assign(const Truck &other);
bool m_leaveOnDestruction = false;
std::string m_arrivalMessage = "A new icecream truck has arrived!\n";
- std::vector<Icecream *> m_flavors;
+ std::vector<IcecreamPtr> m_flavors;
};
#endif // TRUCK_H