Browse Source

Updated pybind11

Former-commit-id: 67536bae05
main
Mavo 9 years ago
committed by Matthias Volk
parent
commit
c99e4de754
  1. 1
      stormpy/resources/pybind11/.travis.yml
  2. 47
      stormpy/resources/pybind11/CMakeLists.txt
  3. 2
      stormpy/resources/pybind11/LICENSE
  4. 3
      stormpy/resources/pybind11/README.md
  5. 2
      stormpy/resources/pybind11/conda.recipe/bld.bat
  6. 3
      stormpy/resources/pybind11/conda.recipe/build.sh
  7. 26
      stormpy/resources/pybind11/conda.recipe/meta.yaml
  8. 4
      stormpy/resources/pybind11/docs/_static/theme_overrides.css
  9. 553
      stormpy/resources/pybind11/docs/advanced.rst
  10. 110
      stormpy/resources/pybind11/docs/basics.rst
  11. 17
      stormpy/resources/pybind11/docs/benchmark.rst
  12. 46
      stormpy/resources/pybind11/docs/changelog.rst
  13. 56
      stormpy/resources/pybind11/docs/compiling.rst
  14. 6
      stormpy/resources/pybind11/docs/conf.py
  15. 154
      stormpy/resources/pybind11/docs/faq.rst
  16. 10
      stormpy/resources/pybind11/docs/index.rst
  17. BIN
      stormpy/resources/pybind11/docs/pybind11_vs_boost_python1.png
  18. BIN
      stormpy/resources/pybind11/docs/pybind11_vs_boost_python2.png
  19. 20
      stormpy/resources/pybind11/docs/release.rst
  20. 73
      stormpy/resources/pybind11/example/eigen.cpp
  21. 44
      stormpy/resources/pybind11/example/eigen.py
  22. 18
      stormpy/resources/pybind11/example/eigen.ref
  23. 12
      stormpy/resources/pybind11/example/example.cpp
  24. 2
      stormpy/resources/pybind11/example/example1.cpp
  25. 4
      stormpy/resources/pybind11/example/example1.ref
  26. 7
      stormpy/resources/pybind11/example/example10.cpp
  27. 5
      stormpy/resources/pybind11/example/example10.py
  28. 3
      stormpy/resources/pybind11/example/example10.ref
  29. 27
      stormpy/resources/pybind11/example/example11.cpp
  30. 10
      stormpy/resources/pybind11/example/example11.py
  31. 10
      stormpy/resources/pybind11/example/example11.ref
  32. 18
      stormpy/resources/pybind11/example/example12.cpp
  33. 2
      stormpy/resources/pybind11/example/example12.ref
  34. 2
      stormpy/resources/pybind11/example/example13.cpp
  35. 50
      stormpy/resources/pybind11/example/example14.cpp
  36. 28
      stormpy/resources/pybind11/example/example14.py
  37. 24
      stormpy/resources/pybind11/example/example14.ref
  38. 2
      stormpy/resources/pybind11/example/example15.cpp
  39. 2
      stormpy/resources/pybind11/example/example15.py
  40. 2
      stormpy/resources/pybind11/example/example16.cpp
  41. 36
      stormpy/resources/pybind11/example/example17.cpp
  42. 40
      stormpy/resources/pybind11/example/example17.py
  43. 10
      stormpy/resources/pybind11/example/example17.ref
  44. 2
      stormpy/resources/pybind11/example/example2.cpp
  45. 2
      stormpy/resources/pybind11/example/example3.cpp
  46. 20
      stormpy/resources/pybind11/example/example3.ref
  47. 2
      stormpy/resources/pybind11/example/example4.cpp
  48. 6
      stormpy/resources/pybind11/example/example5.cpp
  49. 2
      stormpy/resources/pybind11/example/example5.ref
  50. 2
      stormpy/resources/pybind11/example/example6.cpp
  51. 6
      stormpy/resources/pybind11/example/example6.ref
  52. 16
      stormpy/resources/pybind11/example/example7.cpp
  53. 2
      stormpy/resources/pybind11/example/example8.cpp
  54. 2
      stormpy/resources/pybind11/example/example9.cpp
  55. 108
      stormpy/resources/pybind11/example/issues.cpp
  56. 29
      stormpy/resources/pybind11/example/issues.py
  57. 12
      stormpy/resources/pybind11/example/issues.ref
  58. 19
      stormpy/resources/pybind11/include/pybind11/attr.h
  59. 263
      stormpy/resources/pybind11/include/pybind11/cast.h
  60. 146
      stormpy/resources/pybind11/include/pybind11/common.h
  61. 4
      stormpy/resources/pybind11/include/pybind11/complex.h
  62. 2
      stormpy/resources/pybind11/include/pybind11/descr.h
  63. 281
      stormpy/resources/pybind11/include/pybind11/eigen.h
  64. 8
      stormpy/resources/pybind11/include/pybind11/functional.h
  65. 70
      stormpy/resources/pybind11/include/pybind11/numpy.h
  66. 2
      stormpy/resources/pybind11/include/pybind11/operators.h
  67. 335
      stormpy/resources/pybind11/include/pybind11/pybind11.h
  68. 174
      stormpy/resources/pybind11/include/pybind11/pytypes.h
  69. 4
      stormpy/resources/pybind11/include/pybind11/stl.h
  70. 349
      stormpy/resources/pybind11/include/pybind11/stl_bind.h
  71. 2
      stormpy/resources/pybind11/include/pybind11/typeid.h
  72. 4
      stormpy/resources/pybind11/pybind11/__init__.py
  73. 2
      stormpy/resources/pybind11/pybind11/_version.py
  74. 4
      stormpy/resources/pybind11/setup.py
  75. 81
      stormpy/resources/pybind11/tools/FindEigen3.cmake
  76. 200
      stormpy/resources/pybind11/tools/mkdoc.py

1
stormpy/resources/pybind11/.travis.yml

@ -3,6 +3,7 @@ sudo: false
cache:
directories:
- $HOME/.cache/pip
- ccache
addons:
apt:
sources:

47
stormpy/resources/pybind11/CMakeLists.txt

@ -28,7 +28,7 @@ string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE)
set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6 3.7)
if (NOT ${PYBIND11_PYTHON_VERSION} STREQUAL "")
find_package(PythonLibs ${PYBIND11_PYTHON_VERSION} EXACT)
if (NOT PythonLibs_FOUND)
if (NOT PYTHONLIBS_FOUND)
find_package(PythonLibs ${PYBIND11_PYTHON_VERSION} REQUIRED)
endif()
else()
@ -84,24 +84,31 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}"
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
endif()
# Include path for Python header files
include_directories(${PYTHON_INCLUDE_DIR})
# Check if Eigen is available
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tools")
find_package(Eigen3 QUIET)
# Include path for pybind11 header files
include_directories(include)
# Include path for Python header files
include_directories(${PYTHON_INCLUDE_DIR})
set(PYBIND11_HEADERS
include/pybind11/attr.h
include/pybind11/cast.h
include/pybind11/common.h
include/pybind11/complex.h
include/pybind11/descr.h
include/pybind11/eigen.h
include/pybind11/functional.h
include/pybind11/numpy.h
include/pybind11/operators.h
include/pybind11/pybind11.h
include/pybind11/pytypes.h
include/pybind11/stl.h
include/pybind11/stl_bind.h
include/pybind11/typeid.h
)
@ -122,9 +129,19 @@ set(PYBIND11_EXAMPLES
example/example14.cpp
example/example15.cpp
example/example16.cpp
example/example17.cpp
example/issues.cpp
)
if (EIGEN3_FOUND)
include_directories(${EIGEN3_INCLUDE_DIR})
list(APPEND PYBIND11_EXAMPLES example/eigen.cpp)
add_definitions(-DPYBIND11_TEST_EIGEN)
message(STATUS "Building Eigen testcase")
else()
message(STATUS "NOT Building Eigen testcase")
endif()
# Create the binding library
add_library(example SHARED
${PYBIND11_HEADERS}
@ -148,17 +165,19 @@ endforeach()
if (WIN32)
if (MSVC)
# /bigobj is needed for bigger binding projects due to the limit to 64k
# addressable sections. /MP enables multithreaded builds (relevant when
# there are many files).
set_target_properties(example PROPERTIES COMPILE_FLAGS "/MP /bigobj ")
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
# Enforce size-based optimization and link time code generation on MSVC
# (~30% smaller binaries in experiments).
set_target_properties(example APPEND_STRING PROPERTY COMPILE_FLAGS "/Os /GL ")
set_target_properties(example APPEND_STRING PROPERTY LINK_FLAGS "/LTCG ")
endif()
# /MP enables multithreaded builds (relevant when there are many files), /bigobj is
# needed for bigger binding projects due to the limit to 64k addressable sections
set_property(TARGET example APPEND PROPERTY COMPILE_OPTIONS /MP /bigobj)
# Enforce size-based optimization and link time code generation on MSVC
# (~30% smaller binaries in experiments); do nothing in debug mode.
set_property(TARGET example APPEND PROPERTY COMPILE_OPTIONS
"$<$<CONFIG:Release>:/Os>" "$<$<CONFIG:Release>:/GL>"
"$<$<CONFIG:MinSizeRel>:/Os>" "$<$<CONFIG:MinSizeRel>:/GL>"
"$<$<CONFIG:RelWithDebInfo>:/Os>" "$<$<CONFIG:RelWithDebInfo>:/GL>"
)
set_property(TARGET example APPEND_STRING PROPERTY LINK_FLAGS_RELEASE "/LTCG ")
set_property(TARGET example APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL "/LTCG ")
set_property(TARGET example APPEND_STRING PROPERTY LINK_FLAGS_RELWITHDEBINFO "/LTCG ")
endif()
# .PYD file extension on Windows

2
stormpy/resources/pybind11/LICENSE

@ -1,4 +1,4 @@
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>, All rights reserved.
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

3
stormpy/resources/pybind11/README.md

@ -32,6 +32,8 @@ simpler binding code in many common situations.
Tutorial and reference documentation is provided at
[http://pybind11.readthedocs.org/en/latest](http://pybind11.readthedocs.org/en/latest).
A PDF version of the manual is available
[here](https://media.readthedocs.org/pdf/pybind11/latest/pybind11.pdf).
## Core features
pybind11 can map the following core C++ features to Python
@ -97,6 +99,7 @@ Jonas Adler,
Sylvain Corlay,
Axel Huebl,
@hulucc,
Sergey Lyskov
Johan Mabille,
Tomasz Miąsko, and
Ben Pritchard.

2
stormpy/resources/pybind11/conda.recipe/bld.bat

@ -1,2 +0,0 @@
"%PYTHON%" setup.py install --single-version-externally-managed --record=record.txt
if errorlevel 1 exit 1

3
stormpy/resources/pybind11/conda.recipe/build.sh

@ -1,3 +0,0 @@
#!/bin/bash
${PYTHON} setup.py install --single-version-externally-managed --record=record.txt;

26
stormpy/resources/pybind11/conda.recipe/meta.yaml

@ -1,26 +0,0 @@
package:
name: pybind11
version: {{ environ.get('GIT_DESCRIBE_TAG', '').replace('v', '') }}
build:
number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }}
{% if environ.get('GIT_DESCRIBE_NUMBER', '0') == '0' %}string: py{{ environ.get('PY_VER').replace('.', '') }}_0
{% else %}string: py{{ environ.get('PY_VER').replace('.', '') }}_{{ environ.get('GIT_BUILD_STR', 'GIT_STUB') }}{% endif %}
source:
git_url: ../
requirements:
build:
- python
run:
- python
test:
imports:
- pybind11
about:
home: https://github.com/pybind/pybind11/
summary: Seamless operability between C++11 and Python

4
stormpy/resources/pybind11/docs/_static/theme_overrides.css

@ -5,3 +5,7 @@
.rst-content table.docutils td {
vertical-align: top !important;
}
div[class^='highlight'] pre {
white-space: pre;
white-space: pre-wrap;
}

553
stormpy/resources/pybind11/docs/advanced.rst

@ -41,15 +41,18 @@ in C++.
public:
Vector2(float x, float y) : x(x), y(y) { }
std::string toString() const { return "[" + std::to_string(x) + ", " + std::to_string(y) + "]"; }
Vector2 operator+(const Vector2 &v) const { return Vector2(x + v.x, y + v.y); }
Vector2 operator*(float value) const { return Vector2(x * value, y * value); }
Vector2& operator+=(const Vector2 &v) { x += v.x; y += v.y; return *this; }
Vector2& operator*=(float v) { x *= v; y *= v; return *this; }
friend Vector2 operator*(float f, const Vector2 &v) { return Vector2(f * v.x, f * v.y); }
friend Vector2 operator*(float f, const Vector2 &v) {
return Vector2(f * v.x, f * v.y);
}
std::string toString() const {
return "[" + std::to_string(x) + ", " + std::to_string(y) + "]";
}
private:
float x, y;
};
@ -265,8 +268,14 @@ helper class that is defined as follows:
The macro :func:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual
functions, and :func:`PYBIND11_OVERLOAD` should be used for functions which have
a default implementation. The binding code also needs a few minor adaptations
(highlighted):
a default implementation.
There are also two alternate macros :func:`PYBIND11_OVERLOAD_PURE_NAME` and
:func:`PYBIND11_OVERLOAD_NAME` which take a string-valued name argument
after the *Name of the function* slot. This is useful when the C++ and Python
versions of the function have different names, e.g. ``operator()`` vs ``__call__``.
The binding code also needs a few minor adaptations (highlighted):
.. code-block:: cpp
:emphasize-lines: 4,6,7
@ -310,6 +319,15 @@ a virtual method call.
>>> call_go(c)
u'meow! meow! meow! '
.. warning::
Both :func:`PYBIND11_OVERLOAD` and :func:`PYBIND11_OVERLOAD_PURE` are
macros, which means that they can get confused by commas in a template
argument such as ``PYBIND11_OVERLOAD(MyReturnValue<T1, T2>, myFunc)``. In
this case, the preprocessor assumes that the comma indicates the beginnning
of the next parameter. Use a ``typedef`` to bind the template to another
name and use it in the macro to avoid this problem.
.. seealso::
The file :file:`example/example12.cpp` contains a complete example that
@ -411,39 +429,52 @@ For this reason, pybind11 provides a several `return value policy` annotations
that can be passed to the :func:`module::def` and :func:`class_::def`
functions. The default policy is :enum:`return_value_policy::automatic`.
+--------------------------------------------------+---------------------------------------------------------------------------+
| Return value policy | Description |
+==================================================+===========================================================================+
| :enum:`return_value_policy::automatic` | Automatic: copy objects returned as values and take ownership of |
| | objects returned as pointers |
+--------------------------------------------------+---------------------------------------------------------------------------+
| :enum:`return_value_policy::automatic_reference` | Automatic variant 2 : copy objects returned as values and reference |
| | objects returned as pointers |
+--------------------------------------------------+---------------------------------------------------------------------------+
| :enum:`return_value_policy::copy` | Create a new copy of the returned object, which will be owned by Python |
+--------------------------------------------------+---------------------------------------------------------------------------+
| :enum:`return_value_policy::take_ownership` | Reference the existing object and take ownership. Python will call |
| | the destructor and delete operator when the reference count reaches zero |
+--------------------------------------------------+---------------------------------------------------------------------------+
| :enum:`return_value_policy::reference` | Reference the object, but do not take ownership and defer responsibility |
| | for deleting it to C++ (dangerous when C++ code at some point decides to |
| | delete it while Python still has a nonzero reference count) |
+--------------------------------------------------+---------------------------------------------------------------------------+
| :enum:`return_value_policy::reference_internal` | Reference the object, but do not take ownership. The object is considered |
| | be owned by the C++ instance whose method or property returned it. The |
| | Python object will increase the reference count of this 'parent' by 1 |
| | to ensure that it won't be deallocated while Python is using the 'child' |
+--------------------------------------------------+---------------------------------------------------------------------------+
.. warning::
Code with invalid call policies might access unitialized memory and free
data structures multiple times, which can lead to hard-to-debug
non-determinism and segmentation faults, hence it is worth spending the
time to understand all the different options above.
See below for an example that uses the
.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}|
+--------------------------------------------------+----------------------------------------------------------------------------+
| Return value policy | Description |
+==================================================+============================================================================+
| :enum:`return_value_policy::automatic` | This is the default return value policy, which falls back to the policy |
| | :enum:`return_value_policy::take_ownership` when the return value is a |
| | pointer. Otherwise, it uses :enum:`return_value::move` or |
| | :enum:`return_value::copy` for rvalue and lvalue references, respectively. |
| | See below for a description of what all of these different policies do. |
+--------------------------------------------------+----------------------------------------------------------------------------+
| :enum:`return_value_policy::automatic_reference` | As above, but use policy :enum:`return_value_policy::reference` when the |
| | return value is a pointer. You probably won't need to use this. |
+--------------------------------------------------+----------------------------------------------------------------------------+
| :enum:`return_value_policy::take_ownership` | Reference an existing object (i.e. do not create a new copy) and take |
| | ownership. Python will call the destructor and delete operator when the |
| | object's reference count reaches zero. Undefined behavior ensues when the |
| | C++ side does the same.. |
+--------------------------------------------------+----------------------------------------------------------------------------+
| :enum:`return_value_policy::copy` | Create a new copy of the returned object, which will be owned by Python. |
| | This policy is comparably safe because the lifetimes of the two instances |
| | are decoupled. |
+--------------------------------------------------+----------------------------------------------------------------------------+
| :enum:`return_value_policy::move` | Use ``std::move`` to move the return value contents into a new instance |
| | that will be owned by Python. This policy is comparably safe because the |
| | lifetimes of the two instances (move source and destination) are decoupled.|
+--------------------------------------------------+----------------------------------------------------------------------------+
| :enum:`return_value_policy::reference` | Reference an existing object, but do not take ownership. The C++ side is |
| | responsible for managing the object's lifetime and deallocating it when |
| | it is no longer used. Warning: undefined behavior will ensue when the C++ |
| | side deletes an object that is still referenced and used by Python. |
+--------------------------------------------------+----------------------------------------------------------------------------+
| :enum:`return_value_policy::reference_internal` | This policy only applies to methods and properties. It references the |
| | object without taking ownership similar to the above |
| | :enum:`return_value_policy::reference` policy. In contrast to that policy, |
| | the function or property's implicit ``this`` argument (called the *parent*)|
| | is considered to be the the owner of the return value (the *child*). |
| | pybind11 then couples the lifetime of the parent to the child via a |
| | reference relationship that ensures that the parent cannot be garbage |
| | collected while Python is still using the child. More advanced variations |
| | of this scheme are also possible using combinations of |
| | :enum:`return_value_policy::reference` and the :class:`keep_alive` call |
| | policy described next. |
+--------------------------------------------------+----------------------------------------------------------------------------+
The following example snippet shows a use case of the
:enum:`return_value_policy::reference_internal` policy.
.. code-block:: cpp
@ -460,11 +491,36 @@ See below for an example that uses the
py::class_<Example>(m, "Example")
.def(py::init<>())
.def("get_internal", &Example::get_internal, "Return the internal data", py::return_value_policy::reference_internal);
.def("get_internal", &Example::get_internal, "Return the internal data",
py::return_value_policy::reference_internal);
return m.ptr();
}
.. warning::
Code with invalid call policies might access unitialized memory or free
data structures multiple times, which can lead to hard-to-debug
non-determinism and segmentation faults, hence it is worth spending the
time to understand all the different options in the table above.
.. note::
The next section on :ref:`call_policies` discusses *call policies* that can be
specified *in addition* to a return value policy from the list above. Call
policies indicate reference relationships that can involve both return values
and parameters of functions.
.. note::
As an alternative to elaborate call policies and lifetime management logic,
consider using smart pointers (see the section on :ref:`smart_pointers` for
details). Smart pointers can tell whether an object is still referenced from
C++ or Python, which generally eliminates the kinds of inconsistencies that
can lead to crashes or undefined behavior. For functions returning smart
pointers, it is not necessary to specify a return value policy.
.. _call_policies:
Additional call policies
========================
@ -474,12 +530,13 @@ specified to indicate dependencies between parameters. There is currently just
one policy named ``keep_alive<Nurse, Patient>``, which indicates that the
argument with index ``Patient`` should be kept alive at least until the
argument with index ``Nurse`` is freed by the garbage collector; argument
indices start at one, while zero refers to the return value. Arbitrarily many
call policies can be specified.
indices start at one, while zero refers to the return value. For methods, index
one refers to the implicit ``this`` pointer, while regular arguments begin at
index two. Arbitrarily many call policies can be specified.
For instance, binding code for a a list append operation that ties the lifetime
of the newly added element to the underlying container might be declared as
follows:
Consider the following example: the binding code for a list append operation
that ties the lifetime of the newly added element to the underlying container
might be declared as follows:
.. code-block:: cpp
@ -501,7 +558,7 @@ Implicit type conversions
=========================
Suppose that instances of two types ``A`` and ``B`` are used in a project, and
that an ``A`` can easily be converted into a an instance of type ``B`` (examples of this
that an ``A`` can easily be converted into an instance of type ``B`` (examples of this
could be a fixed and an arbitrary precision number type).
.. code-block:: cpp
@ -557,14 +614,16 @@ The above signature would imply that Python needs to give up ownership of an
object that is passed to this function, which is generally not possible (for
instance, the object might be referenced elsewhere).
.. _smart_pointers:
Smart pointers
==============
This section explains how to pass values that are wrapped in "smart" pointer
types with internal reference counting. For simpler C++11 unique pointers,
please refer to the previous section.
types with internal reference counting. For the simpler C++11 unique pointers,
refer to the previous section.
The binding generator for classes (:class:`class_`) takes an optional second
The binding generator for classes, :class:`class_`, takes an optional second
template type, which denotes a special *holder* type that is used to manage
references to the object. When wrapping a type named ``Type``, the default
value of this template parameter is ``std::unique_ptr<Type>``, which means that
@ -708,6 +767,8 @@ automatically converted into a Python ``Exception``. pybind11 defines multiple
special exception classes that will map to different types of Python
exceptions:
.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}|
+--------------------------------------+------------------------------+
| C++ exception type | Python exception type |
+======================================+==============================+
@ -733,6 +794,10 @@ exceptions:
| | accesses in ``__getitem__``, |
| | ``__setitem__``, etc.) |
+--------------------------------------+------------------------------+
| :class:`pybind11::value_error` | ``ValueError`` (used to |
| | indicate wrong value passed |
| | in ``container.remove(...)`` |
+--------------------------------------+------------------------------+
| :class:`pybind11::error_already_set` | Indicates that the Python |
| | exception flag has already |
| | been initialized |
@ -746,13 +811,157 @@ There is also a special exception :class:`cast_error` that is thrown by
:func:`handle::call` when the input arguments cannot be converted to Python
objects.
.. _opaque:
Treating STL data structures as opaque objects
==============================================
pybind11 heavily relies on a template matching mechanism to convert parameters
and return values that are constructed from STL data types such as vectors,
linked lists, hash tables, etc. This even works in a recursive manner, for
instance to deal with lists of hash maps of pairs of elementary and custom
types, etc.
However, a fundamental limitation of this approach is that internal conversions
between Python and C++ types involve a copy operation that prevents
pass-by-reference semantics. What does this mean?
Suppose we bind the following function
.. code-block:: cpp
void append_1(std::vector<int> &v) {
v.push_back(1);
}
and call it from Python, the following happens:
.. code-block:: python
>>> v = [5, 6]
>>> append_1(v)
>>> print(v)
[5, 6]
As you can see, when passing STL data structures by reference, modifications
are not propagated back the Python side. A similar situation arises when
exposing STL data structures using the ``def_readwrite`` or ``def_readonly``
functions:
.. code-block:: cpp
/* ... definition ... */
class MyClass {
std::vector<int> contents;
};
/* ... binding code ... */
py::class_<MyClass>(m, "MyClass")
.def(py::init<>)
.def_readwrite("contents", &MyClass::contents);
In this case, properties can be read and written in their entirety. However, an
``append`` operaton involving such a list type has no effect:
.. code-block:: python
>>> m = MyClass()
>>> m.contents = [5, 6]
>>> print(m.contents)
[5, 6]
>>> m.contents.append(7)
>>> print(m.contents)
[5, 6]
To deal with both of the above situations, pybind11 provides a macro named
``PYBIND11_MAKE_OPAQUE(T)`` that disables the template-based conversion
machinery of types, thus rendering them *opaque*. The contents of opaque
objects are never inspected or extracted, hence they can be passed by
reference. For instance, to turn ``std::vector<int>`` into an opaque type, add
the declaration
.. code-block:: cpp
PYBIND11_MAKE_OPAQUE(std::vector<int>);
before any binding code (e.g. invocations to ``class_::def()``, etc.). This
macro must be specified at the top level, since instantiates a partial template
overload. If your binding code consists of multiple compilation units, it must
be present in every file preceding any usage of ``std::vector<int>``. Opaque
types must also have a corresponding ``class_`` declaration to associate them
with a name in Python, and to define a set of available operations:
.. code-block:: cpp
py::class_<std::vector<int>>(m, "IntVector")
.def(py::init<>())
.def("clear", &std::vector<int>::clear)
.def("pop_back", &std::vector<int>::pop_back)
.def("__len__", [](const std::vector<int> &v) { return v.size(); })
.def("__iter__", [](std::vector<int> &v) {
return py::make_iterator(v.begin(), v.end());
}, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */
// ....
.. seealso::
The file :file:`example/example14.cpp` contains a complete example that
demonstrates how to create and expose opaque types using pybind11 in more
detail.
.. _eigen:
Transparent conversion of dense and sparse Eigen data types
===========================================================
Eigen [#f1]_ is C++ header-based library for dense and sparse linear algebra. Due to
its popularity and widespread adoption, pybind11 provides transparent
conversion support between Eigen and Scientific Python linear algebra data types.
Specifically, when including the optional header file :file:`pybind11/eigen.h`,
pybind11 will automatically and transparently convert
1. Static and dynamic Eigen dense vectors and matrices to instances of
``numpy.ndarray`` (and vice versa).
1. Eigen sparse vectors and matrices to instances of
``scipy.sparse.csr_matrix``/``scipy.sparse.csc_matrix`` (and vice versa).
This makes it possible to bind most kinds of functions that rely on these types.
One major caveat are functions that take Eigen matrices *by reference* and modify
them somehow, in which case the information won't be propagated to the caller.
.. code-block:: cpp
/* The Python bindings of this function won't replicate
the intended effect of modifying the function argument */
void scale_by_2(Eigen::Vector3f &v) {
v *= 2;
}
To see why this is, refer to the section on :ref:`opaque` (although that
section specifically covers STL data types, the underlying issue is the same).
The next two sections discuss an efficient alternative for exposing the
underlying native Eigen types as opaque objects in a way that still integrates
with NumPy and SciPy.
.. [#f1] http://eigen.tuxfamily.org
.. seealso::
The file :file:`example/eigen.cpp` contains a complete example that
shows how to pass Eigen sparse and dense data types in more detail.
Buffer protocol
===============
Python supports an extremely general and convenient approach for exchanging
data between plugin libraries. Types can expose a buffer view [#f1]_,
which provides fast direct access to the raw internal representation. Suppose
we want to bind the following simplistic Matrix class:
data between plugin libraries. Types can expose a buffer view [#f2]_, which
provides fast direct access to the raw internal data representation. Suppose we
want to bind the following simplistic Matrix class:
.. code-block:: cpp
@ -770,7 +979,7 @@ we want to bind the following simplistic Matrix class:
};
The following binding code exposes the ``Matrix`` contents as a buffer object,
making it possible to cast Matrixes into NumPy arrays. It is even possible to
making it possible to cast Matrices into NumPy arrays. It is even possible to
completely avoid copy operations with Python expressions like
``np.array(matrix_instance, copy = False)``.
@ -779,12 +988,12 @@ completely avoid copy operations with Python expressions like
py::class_<Matrix>(m, "Matrix")
.def_buffer([](Matrix &m) -> py::buffer_info {
return py::buffer_info(
m.data(), /* Pointer to buffer */
sizeof(float), /* Size of one scalar */
py::format_descriptor<float>::value(), /* Python struct-style format descriptor */
2, /* Number of dimensions */
{ m.rows(), m.cols() }, /* Buffer dimensions */
{ sizeof(float) * m.rows(), /* Strides (in bytes) for each index */
m.data(), /* Pointer to buffer */
sizeof(float), /* Size of one scalar */
py::format_descriptor<float>::value, /* Python struct-style format descriptor */
2, /* Number of dimensions */
{ m.rows(), m.cols() }, /* Buffer dimensions */
{ sizeof(float) * m.rows(), /* Strides (in bytes) for each index */
sizeof(float) }
);
});
@ -810,41 +1019,71 @@ in a great variety of configurations, hence some safety checks are usually
necessary in the function body. Below, you can see an basic example on how to
define a custom constructor for the Eigen double precision matrix
(``Eigen::MatrixXd``) type, which supports initialization from compatible
buffer
objects (e.g. a NumPy matrix).
buffer objects (e.g. a NumPy matrix).
.. code-block:: cpp
py::class_<Eigen::MatrixXd>(m, "MatrixXd")
.def("__init__", [](Eigen::MatrixXd &m, py::buffer b) {
/* Bind MatrixXd (or some other Eigen type) to Python */
typedef Eigen::MatrixXd Matrix;
typedef Matrix::Scalar Scalar;
constexpr bool rowMajor = Matrix::Flags & Eigen::RowMajorBit;
py::class_<Matrix>(m, "Matrix")
.def("__init__", [](Matrix &m, py::buffer b) {
typedef Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic> Strides;
/* Request a buffer descriptor from Python */
py::buffer_info info = b.request();
/* Some sanity checks ... */
if (info.format != py::format_descriptor<double>::value())
if (info.format != py::format_descriptor<Scalar>::value)
throw std::runtime_error("Incompatible format: expected a double array!");
if (info.ndim != 2)
throw std::runtime_error("Incompatible buffer dimension!");
if (info.strides[0] == sizeof(double)) {
/* Buffer has the right layout -- directly copy. */
new (&m) Eigen::MatrixXd(info.shape[0], info.shape[1]);
memcpy(m.data(), info.ptr, sizeof(double) * m.size());
} else {
/* Oops -- the buffer is transposed */
new (&m) Eigen::MatrixXd(info.shape[1], info.shape[0]);
memcpy(m.data(), info.ptr, sizeof(double) * m.size());
m.transposeInPlace();
}
auto strides = Strides(
info.strides[rowMajor ? 0 : 1] / sizeof(Scalar),
info.strides[rowMajor ? 1 : 0] / sizeof(Scalar));
auto map = Eigen::Map<Matrix, 0, Strides>(
static_cat<Scalar *>(info.ptr), info.shape[0], info.shape[1], strides);
new (&m) Matrix(map);
});
For reference, the ``def_buffer()`` call for this Eigen data type should look
as follows:
.. code-block:: cpp
.def_buffer([](Matrix &m) -> py::buffer_info {
return py::buffer_info(
m.data(), /* Pointer to buffer */
sizeof(Scalar), /* Size of one scalar */
/* Python struct-style format descriptor */
py::format_descriptor<Scalar>::value,
/* Number of dimensions */
2,
/* Buffer dimensions */
{ (size_t) m.rows(),
(size_t) m.cols() },
/* Strides (in bytes) for each index */
{ sizeof(Scalar) * (rowMajor ? m.cols() : 1),
sizeof(Scalar) * (rowMajor ? 1 : m.rows()) }
);
})
For a much easier approach of binding Eigen types (although with some
limitations), refer to the section on :ref:`eigen`.
.. seealso::
The file :file:`example/example7.cpp` contains a complete example that
demonstrates using the buffer protocol with pybind11 in more detail.
.. [#f1] http://docs.python.org/3/c-api/buffer.html
.. [#f2] http://docs.python.org/3/c-api/buffer.html
NumPy support
=============
@ -856,16 +1095,32 @@ type of Python object satisfying the buffer protocol).
In many situations, we want to define a function which only accepts a NumPy
array of a certain data type. This is possible via the ``py::array_t<T>``
template. For instance, the following function requires the argument to be a
dense array of doubles in C-style ordering.
NumPy array containing double precision values.
.. code-block:: cpp
void f(py::array_t<double> array);
When it is invoked with a different type (e.g. an integer), the binding code
will attempt to cast the input into a NumPy array of the requested type. Note
that this feature requires the :file:``pybind11/numpy.h`` header to be
included.
When it is invoked with a different type (e.g. an integer or a list of
integers), the binding code will attempt to cast the input into a NumPy array
of the requested type. Note that this feature requires the
:file:``pybind11/numpy.h`` header to be included.
Data in NumPy arrays is not guaranteed to packed in a dense manner;
furthermore, entries can be separated by arbitrary column and row strides.
Sometimes, it can be useful to require a function to only accept dense arrays
using either the C (row-major) or Fortran (column-major) ordering. This can be
accomplished via a second template argument with values ``py::array::c_style``
or ``py::array::f_style``.
.. code-block:: cpp
void f(py::array_t<double, py::array::c_style | py::array::forcecast> array);
The ``py::array::forcecast`` argument is the default value of the second
template paramenter, and it ensures that non-conforming arguments are converted
into an array satisfying the specified requirements instead of trying the next
function overload.
Vectorizing functions
=====================
@ -885,7 +1140,7 @@ After including the ``pybind11/numpy.h`` header, this is extremely simple:
m.def("vectorized_func", py::vectorize(my_func));
Invoking the function like below causes 4 calls to be made to ``my_func`` with
each of the the array elements. The significant advantage of this compared to
each of the array elements. The significant advantage of this compared to
solutions like ``numpy.vectorize()`` is that the loop over the elements runs
entirely on the C++ side and can be crunched down into a tight, optimized loop
by the compiler. The result is returned as a NumPy array of type
@ -903,7 +1158,7 @@ arrays ``x`` and ``y`` are automatically converted into the right types (they
are of type ``numpy.dtype.int64`` but need to be ``numpy.dtype.int32`` and
``numpy.dtype.float32``, respectively)
Sometimes we might want to explitly exclude an argument from the vectorization
Sometimes we might want to explicitly exclude an argument from the vectorization
because it makes little sense to wrap it in a NumPy array. For instance,
suppose the function signature was
@ -996,8 +1251,9 @@ For instance, the following statement iterates over a Python ``dict``:
Available types include :class:`handle`, :class:`object`, :class:`bool_`,
:class:`int_`, :class:`float_`, :class:`str`, :class:`bytes`, :class:`tuple`,
:class:`list`, :class:`dict`, :class:`slice`, :class:`capsule`,
:class:`function`, :class:`buffer`, :class:`array`, and :class:`array_t`.
:class:`list`, :class:`dict`, :class:`slice`, :class:`none`, :class:`capsule`,
:class:`iterable`, :class:`iterator`, :class:`function`, :class:`buffer`,
:class:`array`, and :class:`array_t`.
In this kind of mixed code, it is often necessary to convert arbitrary C++
types to Python, which can be done using :func:`cast`:
@ -1015,11 +1271,31 @@ The reverse direction uses the following syntax:
MyClass *cls = obj.cast<MyClass *>();
When conversion fails, both directions throw the exception :class:`cast_error`.
It is also possible to call python functions via ``operator()``.
.. code-block:: cpp
py::function f = <...>;
py::object result_py = f(1234, "hello", some_instance);
MyClass &result = result_py.cast<MyClass>();
The special ``f(*args)`` and ``f(*args, **kwargs)`` syntax is also supported to
supply arbitrary argument and keyword lists, although these cannot be mixed
with other parameters.
.. code-block:: cpp
py::function f = <...>;
py::tuple args = py::make_tuple(1234);
py::dict kwargs;
kwargs["y"] = py::cast(5678);
py::object result = f(*args, **kwargs);
.. seealso::
The file :file:`example/example2.cpp` contains a complete example that
demonstrates passing native Python types in more detail.
demonstrates passing native Python types in more detail. The file
:file:`example/example11.cpp` discusses usage of ``args`` and ``kwargs``.
Default arguments revisited
===========================
@ -1068,6 +1344,36 @@ like so:
py::class_<MyClass>("MyClass")
.def("myFunction", py::arg("arg") = (SomeType *) nullptr);
Binding functions that accept arbitrary numbers of arguments and keywords arguments
===================================================================================
Python provides a useful mechanism to define functions that accept arbitrary
numbers of arguments and keyword arguments:
.. code-block:: cpp
def generic(*args, **kwargs):
# .. do something with args and kwargs
Such functions can also be created using pybind11:
.. code-block:: cpp
void generic(py::args args, py::kwargs kwargs) {
/// .. do something with args
if (kwargs)
/// .. do something with kwargs
}
/// Binding code
m.def("generic", &generic);
(See ``example/example11.cpp``). The class ``py::args`` derives from
``py::list`` and ``py::kwargs`` derives from ``py::dict`` Note that the
``kwargs`` argument is invalid if no keyword arguments were actually provided.
Please refer to the other examples for details on how to iterate over these,
and on how to cast their entries into C++ objects.
Partitioning code over multiple extension modules
=================================================
@ -1136,58 +1442,6 @@ accessed by multiple extension modules:
};
Treating STL data structures as opaque objects
==============================================
pybind11 heavily relies on a template matching mechanism to convert parameters
and return values that are constructed from STL data types such as vectors,
linked lists, hash tables, etc. This even works in a recursive manner, for
instance to deal with lists of hash maps of pairs of elementary and custom
types, etc.
A fundamental limitation of this approach is that the internal conversion
between Python and C++ types involves a copy operation that prevents
pass-by-reference semantics. What does this mean?
Suppose we bind the following function
.. code-block:: cpp
void append_1(std::vector<int> &v) {
v.push_back(1);
}
and call it as follows from Python:
.. code-block:: python
>>> v = [5, 6]
>>> append_1(v)
>>> print(v)
[5, 6]
As you can see, when passing STL data structures by reference, modifications
are not propagated back the Python side. To deal with situations where this
desirable, pybind11 contains a simple template wrapper class named ``opaque<T>``.
``opaque<T>`` disables the underlying template machinery for
``T`` and can be used to treat STL types as opaque objects, whose contents are
never inspected or extracted (thus, they can be passed by reference).
The downside of this approach is that it the binding code becomes a bit more
wordy. The above function can be bound using the following wrapper code:
.. code-block:: cpp
m.def("append_1", [](py::opaque<std::vector<int>> &v) { append_1(v); });
Opaque types must also have a dedicated ``class_`` declaration to define a
set of admissible operations.
.. seealso::
The file :file:`example/example14.cpp` contains a complete example that
demonstrates how to create opaque types using pybind11 in more detail.
Pickling support
================
@ -1210,7 +1464,7 @@ Suppose the class in question has the following signature:
int m_extra = 0;
};
The binding code including the requisite ``__setstate__`` and ``__getstate__`` methods [#f2]_
The binding code including the requisite ``__setstate__`` and ``__getstate__`` methods [#f3]_
looks as follows:
.. code-block:: cpp
@ -1247,27 +1501,29 @@ An instance can now be pickled as follows:
p = Pickleable("test_value")
p.setExtra(15)
data = pickle.dumps(p, -1)
data = pickle.dumps(p, 2)
Note that only the cPickle module is supported on Python 2.7. It is also
important to request usage of the highest protocol version using the ``-1``
argument to ``dumps``. Failure to follow these two steps will lead to important
pybind11 memory allocation routines to be skipped during unpickling, which will
likely cause memory corruption and/or segmentation faults.
Note that only the cPickle module is supported on Python 2.7. The second
argument to ``dumps`` is also crucial: it selects the pickle protocol version
2, since the older version 1 is not supported. Newer versions are also fine—for
instance, specify ``-1`` to always use the latest available version. Beware:
failure to follow these instructions will cause important pybind11 memory
allocation routines to be skipped during unpickling, which will likely lead to
memory corruption and/or segmentation faults.
.. seealso::
The file :file:`example/example15.cpp` contains a complete example that
demonstrates how to pickle and unpickle types using pybind11 in more detail.
.. [#f2] http://docs.python.org/3/library/pickle.html#pickling-class-instances
.. [#f3] http://docs.python.org/3/library/pickle.html#pickling-class-instances
Generating documentation using Sphinx
=====================================
Sphinx [#f3]_ has the ability to inspect the signatures and documentation
Sphinx [#f4]_ has the ability to inspect the signatures and documentation
strings in pybind11-based extension modules to automatically generate beautiful
documentation in a variety formats. The pbtest repository [#f4]_ contains a
documentation in a variety formats. The pbtest repository [#f5]_ contains a
simple example repository which uses this approach.
There are two potential gotchas when using this approach: first, make sure that
@ -1294,6 +1550,5 @@ work, it is important that all lines are indented consistently, i.e.:
----------
)mydelimiter");
.. [#f3] http://www.sphinx-doc.org
.. [#f4] http://github.com/pybind/pbtest
.. [#f4] http://www.sphinx-doc.org
.. [#f5] http://github.com/pybind/pbtest

110
stormpy/resources/pybind11/docs/basics.rst

@ -117,7 +117,7 @@ example can be compiled using the following command
.. code-block:: bash
$ c++ -O3 -shared -std=c++11 -I <path-to-pybind11>/include `python-config --cflags --ldflags --libs` example.cpp -o example.so
$ c++ -O3 -shared -std=c++11 -I <path-to-pybind11>/include `python-config --cflags --ldflags` example.cpp -o example.so
In general, it is advisable to include several additional build parameters
that can considerably reduce the size of the created binary. Refer to section
@ -222,57 +222,63 @@ The following basic data types are supported out of the box (some may require
an additional extension header to be included). To pass other data structures
as arguments and return values, refer to the section on binding :ref:`classes`.
+----------------------------+--------------------------+-----------------------+
| Data type | Description | Header file |
+============================+==========================+=======================+
| int8_t, uint8_t | 8-bit integers | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| int16_t, uint16_t | 16-bit integers | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| int32_t, uint32_t | 32-bit integers | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| int64_t, uint64_t | 64-bit integers | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| ssize_t, size_t | Platform-dependent size | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| float, double | Floating point types | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| bool | Two-state Boolean type | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| char | Character literal | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| wchar_t | Wide character literal | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| const char * | UTF-8 string literal | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| const wchar_t * | Wide string literal | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| std::string | STL dynamic UTF-8 string | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| std::wstring | STL dynamic wide string | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| std::pair<T1, T2> | Pair of two custom types | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| std::tuple<....> | Arbitrary tuple of types | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| std::complex<T> | Complex numbers | pybind11/complex.h |
+----------------------------+--------------------------+-----------------------+
| std::array<T, Size> | STL static array | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::vector<T> | STL dynamic array | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::list<T> | STL linked list | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::map<T1, T2> | STL ordered map | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::unordered_map<T1, T2> | STL unordered map | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::set<T> | STL ordered set | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::unordered_set<T> | STL unordered set | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::function<...> | STL polymorphic function | pybind11/functional.h |
+----------------------------+--------------------------+-----------------------+
+---------------------------------+--------------------------+-------------------------------+
| Data type | Description | Header file |
+=================================+==========================+===============================+
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``Eigen::Matrix<...>`` | Dense Eigen matrices | :file:`pybind11/eigen.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``Eigen::SparseMatrix<...>`` | Sparse Eigen matrices | :file:`pybind11/eigen.h` |
+---------------------------------+--------------------------+-------------------------------+
.. [#f1] In practice, implementation and binding code will generally be located

17
stormpy/resources/pybind11/docs/benchmark.rst

@ -65,7 +65,13 @@ the largest largest file with 2048 classes and a total of 8192 methods -- a
modest **1.2x** speedup relative to Boost.Python, which required 116.35
seconds).
.. image:: pybind11_vs_boost_python1.svg
.. only:: not latex
.. image:: pybind11_vs_boost_python1.svg
.. only:: latex
.. image:: pybind11_vs_boost_python1.png
Module size
-----------
@ -79,5 +85,12 @@ that it stores many definitions in an external library, whose size was not
included here, hence the comparison is slightly shifted in Boost.Python's
favor.
.. image:: pybind11_vs_boost_python2.svg
.. only:: not latex
.. image:: pybind11_vs_boost_python2.svg
.. only:: latex
.. image:: pybind11_vs_boost_python2.png

46
stormpy/resources/pybind11/docs/changelog.rst

@ -3,9 +3,50 @@
Changelog
#########
1.5 (not yet released)
1.8 (Not yet released)
----------------------
* For polymorphic types, use RTTI to try to return the closest type registered with pybind11.
* Prevent implicit conversion of floating point values to integral types in
function arguments
* Transparent conversion of sparse and dense Eigen data types
* Fixed incorrect default return value policy for functions returning a shared
pointer
* Don't allow casting a ``None`` value into a C++ lvalue reference
* Fixed a crash in ``enum_::operator==`` that was triggered by the ``help()`` command
* Improved detection of whether or not custom C++ types can be copy/move-constructed
* Extended ``str`` type to also work with ``bytes`` instances
* Added ``[[noreturn]]`` attribute to ``pybind11_fail()`` to quench some
compiler warnings
* Various minor ``iterator`` and ``make_iterator()`` improvements
* Minor CMake build system improvements on Windows
* Many ``mkdoc.py`` improvements (enumerations, template arguments, ``DOC()``
macro accepts more arguments)
* Documentation improvements (pickling support, ``keep_alive``)
1.7 (April 30, 2016)
----------------------
* Added a new ``move`` return value policy that triggers C++11 move semantics.
The automatic return value policy falls back to this case whenever a rvalue
reference is encountered
* Significantly more general GIL state routines that are used instead of
Python's troublesome ``PyGILState_Ensure`` and ``PyGILState_Release`` API
* Redesign of opaque types that drastically simplifies their usage
* Extended ability to pass values of type ``[const] void *``
* ``keep_alive`` fix: don't fail when there is no patient
* ``functional.h``: acquire the GIL before calling a Python function
* Added Python RAII type wrappers ``none`` and ``iterable``
* Added ``*args`` and ``*kwargs`` pass-through parameters to
``pybind11.get_include()`` function
* Iterator improvements and fixes
* Documentation on return value policies and opaque types improved
1.6 (April 30, 2016)
----------------------
* Skipped due to upload to PyPI gone wrong and inability to recover
(https://github.com/pypa/packaging-problems/issues/74)
1.5 (April 21, 2016)
----------------------
* For polymorphic types, use RTTI to try to return the closest type registered with pybind11
* Pickling support for serializing and unserializing C++ instances to a byte stream in Python
* Added a convenience routine ``make_iterator()`` which turns a range indicated
by a pair of C++ iterators into a iterable Python object
@ -16,6 +57,7 @@ Changelog
* Added a ``get_include()`` function to the Python module that returns the path
of the directory containing the installed pybind11 header files
* Documentation improvements: import issues, symbol visibility, pickling, limitations
* Added casting support for ``std::reference_wrapper<>``
1.4 (April 7, 2016)
--------------------------

56
stormpy/resources/pybind11/docs/cmake.rst → stormpy/resources/pybind11/docs/compiling.rst

@ -11,6 +11,16 @@ the [pbtest]_ repository.
.. [pbtest] https://github.com/pybind/pbtest
Building with cppimport
========================
cppimport is a small Python import hook that determines whether there is a C++
source file whose name matches the requested module. If there is, the file is
compiled as a Python extension using pybind11 and placed in the same folder as
the C++ source file. Python is then able to find the module and load it.
.. [cppimport] https://github.com/tbenthompson/cppimport
.. _cmake:
Building with CMake
@ -29,11 +39,13 @@ subdirectory named :file:`pybind11`.
project(example)
# Add a CMake parameter for choosing a desired Python version
set(EXAMPLE_PYTHON_VERSION "" CACHE STRING "Python version to use for compiling the example library")
set(EXAMPLE_PYTHON_VERSION "" CACHE STRING
"Python version to use for compiling the example library")
include(CheckCXXCompilerFlag)
# Set a default build configuration if none is specified. 'MinSizeRel' produces the smallest binaries
# Set a default build configuration if none is specified.
# 'MinSizeRel' produces the smallest binaries
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'MinSizeRel' as none was specified.")
set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build." FORCE)
@ -46,14 +58,15 @@ subdirectory named :file:`pybind11`.
set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6 3.7)
if (NOT ${EXAMPLE_PYTHON_VERSION} STREQUAL "")
find_package(PythonLibs ${EXAMPLE_PYTHON_VERSION} EXACT)
if (NOT PythonLibs_FOUND)
if (NOT PYTHONLIBS_FOUND)
find_package(PythonLibs ${EXAMPLE_PYTHON_VERSION} REQUIRED)
endif()
else()
find_package(PythonLibs REQUIRED)
endif()
# The above sometimes returns version numbers like "3.4.3+"; the "+" must be removed for the next lines to work
# The above sometimes returns version numbers like "3.4.3+";
# the "+" must be removed for the next lines to work
string(REPLACE "+" "" PYTHONLIBS_VERSION_STRING "+${PYTHONLIBS_VERSION_STRING}")
# Uncomment the following line if you will also require a matching Python interpreter
@ -88,7 +101,8 @@ subdirectory named :file:`pybind11`.
# Include path for Python header files
include_directories(${PYTHON_INCLUDE_DIR})
# Include path for pybind11 header files -- this may need to be changed depending on your setup
# Include path for pybind11 header files -- this may need to be
# changed depending on your setup
include_directories(${PROJECT_SOURCE_DIR}/pybind11/include)
# Create the binding library
@ -102,17 +116,19 @@ subdirectory named :file:`pybind11`.
if (WIN32)
if (MSVC)
# /bigobj is needed for bigger binding projects due to the limit to 64k
# addressable sections. /MP enables multithreaded builds (relevant when
# there are many files).
set_target_properties(example PROPERTIES COMPILE_FLAGS "/MP /bigobj ")
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
# Enforce size-based optimization and link time code generation on MSVC
# (~30% smaller binaries in experiments).
set_target_properties(example APPEND_STRING PROPERTY COMPILE_FLAGS "/Os /GL ")
set_target_properties(example APPEND_STRING PROPERTY LINK_FLAGS "/LTCG ")
endif()
# /MP enables multithreaded builds (relevant when there are many files), /bigobj is
# needed for bigger binding projects due to the limit to 64k addressable sections
set_property(TARGET example APPEND PROPERTY COMPILE_OPTIONS /MP /bigobj)
# Enforce size-based optimization and link time code generation on MSVC
# (~30% smaller binaries in experiments); do nothing in debug mode.
set_property(TARGET example APPEND PROPERTY COMPILE_OPTIONS
"$<$<CONFIG:Release>:/Os>" "$<$<CONFIG:Release>:/GL>"
"$<$<CONFIG:MinSizeRel>:/Os>" "$<$<CONFIG:MinSizeRel>:/GL>"
"$<$<CONFIG:RelWithDebInfo>:/Os>" "$<$<CONFIG:RelWithDebInfo>:/GL>"
)
set_property(TARGET example APPEND_STRING PROPERTY LINK_FLAGS_RELEASE "/LTCG ")
set_property(TARGET example APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL "/LTCG ")
set_property(TARGET example APPEND_STRING PROPERTY LINK_FLAGS_RELWITHDEBINFO "/LTCG ")
endif()
# .PYD file extension on Windows
@ -143,11 +159,13 @@ subdirectory named :file:`pybind11`.
set_target_properties(example PROPERTIES MACOSX_RPATH ".")
set_target_properties(example PROPERTIES LINK_FLAGS "-undefined dynamic_lookup ")
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
add_custom_command(TARGET example POST_BUILD COMMAND strip -u -r ${PROJECT_BINARY_DIR}/example.so)
add_custom_command(TARGET example POST_BUILD
COMMAND strip -u -r ${PROJECT_BINARY_DIR}/example.so)
endif()
else()
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
add_custom_command(TARGET example POST_BUILD COMMAND strip ${PROJECT_BINARY_DIR}/example.so)
add_custom_command(TARGET example POST_BUILD
COMMAND strip ${PROJECT_BINARY_DIR}/example.so)
endif()
endif()
endif()

6
stormpy/resources/pybind11/docs/conf.py

@ -158,7 +158,7 @@ else:
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['.static']
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
@ -233,7 +233,7 @@ latex_elements = {
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
'preamble': '\DeclareUnicodeCharacter{00A0}{}',
# Latex figure (float) alignment
#'figure_align': 'htbp',
@ -249,7 +249,7 @@ latex_documents = [
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = 'pybind11-logo.png'
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.

154
stormpy/resources/pybind11/docs/faq.rst

@ -1,10 +1,8 @@
Frequently asked questions
##########################
(under construction)
ImportError: dynamic module does not define init function
=========================================================
"ImportError: dynamic module does not define init function"
===========================================================
1. Make sure that the name specified in ``pybind::module`` and
``PYBIND11_PLUGIN`` is consistent and identical to the filename of the
@ -14,7 +12,36 @@ ImportError: dynamic module does not define init function
2. If the above did not fix your issue, then you are likely using an
incompatible version of Python (for instance, the extension library was
compiled against Python 2, while the interpreter is running on top of some
version of Python 3)
version of Python 3, or vice versa)
"Symbol not found: ``__Py_ZeroStruct`` / ``_PyInstanceMethod_Type``"
========================================================================
See item 2 of the first answer.
The Python interpreter immediately crashes when importing my module
===================================================================
See item 2 of the first answer.
CMake doesn't detect the right Python version, or it finds mismatched interpreter and library versions
======================================================================================================
The Python detection logic of CMake is flawed and can sometimes fail to find
the desired Python version, or it chooses mismatched interpreter and library
versions. A longer discussion is available on the pybind11 issue tracker
[#f1]_, though this is ultimately not a pybind11 issue.
To force the build system to choose a particular version, delete CMakeCache.txt
and then invoke CMake as follows:
.. code-block:: bash
cmake -DPYTHON_EXECUTABLE:FILEPATH=<...> \
-DPYTHON_LIBRARY:FILEPATH=<...> \
-DPYTHON_INCLUDE_DIR:PATH=<...> .
.. [#f1] http://github.com/pybind/pybind11/issues/99
Limitations involving reference arguments
=========================================
@ -64,24 +91,114 @@ and the binding code
m.def("foo", [](int i) { int rv = foo(i); return std::make_tuple(rv, i); });
CMake doesn't detect the right Python version, or it finds mismatched interpreter and library versions
======================================================================================================
The Python detection logic of CMake is flawed and can sometimes fail to find
the desired Python version, or it chooses mismatched interpreter and library
versions. A longer discussion is available on the pybind11 issue tracker
[#f1]_, though this is ultimately not a pybind11 issue.
How can I reduce the build time?
================================
To force the build system to choose a particular version, delete CMakeCache.txt
and then invoke CMake as follows:
It's good practice to split binding code over multiple files, as is done in
the included file :file:`example/example.cpp`.
.. code-block:: bash
.. code-block:: cpp
cmake -DPYTHON_EXECUTABLE:FILEPATH=<...> \
-DPYTHON_LIBRARY:FILEPATH=<...> \
-DPYTHON_INCLUDE_DIR:PATH=<...> .
void init_ex1(py::module &);
void init_ex2(py::module &);
/* ... */
.. [#f1] http://github.com/pybind/pybind11/issues/99
PYBIND11_PLUGIN(example) {
py::module m("example", "pybind example plugin");
init_ex1(m);
init_ex2(m);
/* ... */
return m.ptr();
}
The various ``init_ex`` functions should be contained in separate files that
can be compiled independently from another. Following this approach will
1. reduce memory requirements per compilation unit.
2. enable parallel builds (if desired).
3. allow for faster incremental builds. For instance, when a single class
definiton is changed, only a subset of the binding code will generally need
to be recompiled.
How can I create smaller binaries?
==================================
To do its job, pybind11 extensively relies on a programming technique known as
*template metaprogramming*, which is a way of performing computation at compile
time using type information. Template metaprogamming usually instantiates code
involving significant numbers of deeply nested types that are either completely
removed or reduced to just a few instrutions during the compiler's optimization
phase. However, due to the nested nature of these types, the resulting symbol
names in the compiled extension library can be extremely long. For instance,
the included test suite contains the following symbol:
.. only:: html
.. code-block:: none
_​_​Z​N​8​p​y​b​i​n​d​1​1​1​2​c​p​p​_​f​u​n​c​t​i​o​n​C​1​I​v​8​E​x​a​m​p​l​e​2​J​R​N​S​t​3​_​_​1​6​v​e​c​t​o​r​I​N​S​3​_​1​2​b​a​s​i​c​_​s​t​r​i​n​g​I​w​N​S​3​_​1​1​c​h​a​r​_​t​r​a​i​t​s​I​w​E​E​N​S​3​_​9​a​l​l​o​c​a​t​o​r​I​w​E​E​E​E​N​S​8​_​I​S​A​_​E​E​E​E​E​J​N​S​_​4​n​a​m​e​E​N​S​_​7​s​i​b​l​i​n​g​E​N​S​_​9​i​s​_​m​e​t​h​o​d​E​A​2​8​_​c​E​E​E​M​T​0​_​F​T​_​D​p​T​1​_​E​D​p​R​K​T​2​_​
.. only:: not html
.. code-block:: cpp
__ZN8pybind1112cpp_functionC1Iv8Example2JRNSt3__16vectorINS3_12basic_stringIwNS3_11char_traitsIwEENS3_9allocatorIwEEEENS8_ISA_EEEEEJNS_4nameENS_7siblingENS_9is_methodEA28_cEEEMT0_FT_DpT1_EDpRKT2_
which is the mangled form of the following function type:
.. code-block:: cpp
pybind11::cpp_function::cpp_function<void, Example2, std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&, pybind11::name, pybind11::sibling, pybind11::is_method, char [28]>(void (Example2::*)(std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&), pybind11::name const&, pybind11::sibling const&, pybind11::is_method const&, char const (&) [28])
The memory needed to store just the mangled name of this function (196 bytes)
is larger than the actual piece of code (111 bytes) it represents! On the other
hand, it's silly to even give this function a name -- after all, it's just a
tiny cog in a bigger piece of machinery that is not exposed to the outside
world. So we'll generally only want to export symbols for those functions which
are actually called from the outside.
This can be achieved by specifying the parameter ``-fvisibility=hidden`` to GCC
and Clang, which sets the default symbol visibility to *hidden*. It's best to
do this only for release builds, since the symbol names can be helpful in
debugging sessions. On Visual Studio, symbols are already hidden by default, so
nothing needs to be done there. Needless to say, this has a tremendous impact
on the final binary size of the resulting extension library.
Another aspect that can require a fair bit of code are function signature
descriptions. pybind11 automatically generates human-readable function
signatures for docstrings, e.g.:
.. code-block:: none
| __init__(...)
| __init__(*args, **kwargs)
| Overloaded function.
|
| 1. __init__(example.Example1) -> NoneType
|
| Docstring for overload #1 goes here
|
| 2. __init__(example.Example1, int) -> NoneType
|
| Docstring for overload #2 goes here
|
| 3. __init__(example.Example1, example.Example1) -> NoneType
|
| Docstring for overload #3 goes here
In C++11 mode, these are generated at run time using string concatenation,
which can amount to 10-20% of the size of the resulting binary. If you can,
enable C++14 language features (using ``-std=c++14`` for GCC/Clang), in which
case signatures are efficiently pre-generated at compile time. Unfortunately,
Visual Studio's C++14 support (``constexpr``) is not good enough as of April
2016, so it always uses the more expensive run-time approach.
Working with ancient Visual Studio 2009 builds on Windows
=========================================================
@ -96,4 +213,3 @@ Common gotchas to watch out for involve not ``free()``-ing memory region
that that were ``malloc()``-ed in another shared library, using data
structures with incompatible ABIs, and so on. pybind11 is very careful not
to make these types of mistakes.

10
stormpy/resources/pybind11/docs/index.rst

@ -1,9 +1,13 @@
.. image:: pybind11-logo.png
.. only: not latex
.. image:: pybind11-logo.png
pybind11 --- Seamless operability between C++11 and Python
==========================================================
Contents:
.. only: not latex
Contents:
.. toctree::
:maxdepth: 2
@ -12,7 +16,7 @@ Contents:
basics
classes
advanced
cmake
compiling
benchmark
limitations
faq

BIN
stormpy/resources/pybind11/docs/pybind11_vs_boost_python1.png

After

Width: 975  |  Height: 525  |  Size: 44 KiB

BIN
stormpy/resources/pybind11/docs/pybind11_vs_boost_python2.png

After

Width: 975  |  Height: 513  |  Size: 40 KiB

20
stormpy/resources/pybind11/docs/release.rst

@ -2,20 +2,18 @@ To release a new version of pybind11:
- Update the version number and push to pypi
- Update ``pybind11/_version.py`` (set release version, remove 'dev')
- Tag release date in ``doc/changelog.rst``.
- ``git add`` and ``git commit``.
- ``git tag -a vX.Y -m 'vX.Y release'``.
- ``git push``
- ``git push --tags``.
- ``python setup.py sdist upload``.
- ``python setup.py bdist_wheel upload``.
- Tag release date in ``doc/changelog.rst``.
- Tag the commit and push to anaconda.org
- ``git tag -a X.X -m '[Release comment]'``.
- ``conda-build conda.recipe --output``
This should ouput the path of the generated tar.bz2 for the package
- ``conda-convert --platform all [path/to/tar.bz2] -o .``
- ``for i in *-32/* *-64/*; do anaconda upload -u pybind $i; done``
- Update conda-forge (https://github.com/conda-forge/pybind11-feedstock)
- change version number in ``meta.yml``
- update checksum to match the one computed by pypi
- Get back to work
- Update ``_version.py`` (add 'dev' and increment minor).
- Update version macros in ``include/pybind11/common.h``
- ``git add`` and ``git commit``. ``git push``. ``git push --tags``.
The remote for the last ``git push --tags`` should be the main repository for
pybind11.
- ``git add`` and ``git commit``.
``git push``

73
stormpy/resources/pybind11/example/eigen.cpp

@ -0,0 +1,73 @@
/*
example/eigen.cpp -- automatic conversion of Eigen types
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
#include <pybind11/eigen.h>
void init_eigen(py::module &m) {
typedef Eigen::Matrix<float, 5, 6, Eigen::RowMajor> FixedMatrixR;
typedef Eigen::Matrix<float, 5, 6> FixedMatrixC;
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> DenseMatrixR;
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> DenseMatrixC;
typedef Eigen::SparseMatrix<float, Eigen::RowMajor> SparseMatrixR;
typedef Eigen::SparseMatrix<float> SparseMatrixC;
// Non-symmetric matrix with zero elements
Eigen::MatrixXf mat(5, 6);
mat << 0, 3, 0, 0, 0, 11, 22, 0, 0, 0, 17, 11, 7, 5, 0, 1, 0, 11, 0,
0, 0, 0, 0, 11, 0, 0, 14, 0, 8, 11;
m.def("fixed_r", [mat]() -> FixedMatrixR {
return FixedMatrixR(mat);
});
m.def("fixed_c", [mat]() -> FixedMatrixC {
return FixedMatrixC(mat);
});
m.def("fixed_passthrough_r", [](const FixedMatrixR &m) -> FixedMatrixR {
return m;
});
m.def("fixed_passthrough_c", [](const FixedMatrixC &m) -> FixedMatrixC {
return m;
});
m.def("dense_r", [mat]() -> DenseMatrixR {
return DenseMatrixR(mat);
});
m.def("dense_c", [mat]() -> DenseMatrixC {
return DenseMatrixC(mat);
});
m.def("dense_passthrough_r", [](const DenseMatrixR &m) -> DenseMatrixR {
return m;
});
m.def("dense_passthrough_c", [](const DenseMatrixC &m) -> DenseMatrixC {
return m;
});
m.def("sparse_r", [mat]() -> SparseMatrixR {
return Eigen::SparseView<Eigen::MatrixXf>(mat);
});
m.def("sparse_c", [mat]() -> SparseMatrixC {
return Eigen::SparseView<Eigen::MatrixXf>(mat);
});
m.def("sparse_passthrough_r", [](const SparseMatrixR &m) -> SparseMatrixR {
return m;
});
m.def("sparse_passthrough_c", [](const SparseMatrixC &m) -> SparseMatrixC {
return m;
});
}

44
stormpy/resources/pybind11/example/eigen.py

@ -0,0 +1,44 @@
#!/usr/bin/env python
from __future__ import print_function
import sys
sys.path.append('.')
from example import fixed_r, fixed_c
from example import fixed_passthrough_r, fixed_passthrough_c
from example import dense_r, dense_c
from example import dense_passthrough_r, dense_passthrough_c
from example import sparse_r, sparse_c
from example import sparse_passthrough_r, sparse_passthrough_c
import numpy as np
ref = np.array(
[[0, 3, 0, 0, 0, 11],
[22, 0, 0, 0, 17, 11],
[7, 5, 0, 1, 0, 11],
[0, 0, 0, 0, 0, 11],
[0, 0, 14, 0, 8, 11]])
def check(mat):
return 'OK' if np.sum(mat - ref) == 0 else 'NOT OK'
print("fixed_r = %s" % check(fixed_r()))
print("fixed_c = %s" % check(fixed_c()))
print("pt_r(fixed_r) = %s" % check(fixed_passthrough_r(fixed_r())))
print("pt_c(fixed_c) = %s" % check(fixed_passthrough_c(fixed_c())))
print("pt_r(fixed_c) = %s" % check(fixed_passthrough_r(fixed_c())))
print("pt_c(fixed_r) = %s" % check(fixed_passthrough_c(fixed_r())))
print("dense_r = %s" % check(dense_r()))
print("dense_c = %s" % check(dense_c()))
print("pt_r(dense_r) = %s" % check(dense_passthrough_r(dense_r())))
print("pt_c(dense_c) = %s" % check(dense_passthrough_c(dense_c())))
print("pt_r(dense_c) = %s" % check(dense_passthrough_r(dense_c())))
print("pt_c(dense_r) = %s" % check(dense_passthrough_c(dense_r())))
print("sparse_r = %s" % check(sparse_r()))
print("sparse_c = %s" % check(sparse_c()))
print("pt_r(sparse_r) = %s" % check(sparse_passthrough_r(sparse_r())))
print("pt_c(sparse_c) = %s" % check(sparse_passthrough_c(sparse_c())))
print("pt_r(sparse_c) = %s" % check(sparse_passthrough_r(sparse_c())))
print("pt_c(sparse_r) = %s" % check(sparse_passthrough_c(sparse_r())))

18
stormpy/resources/pybind11/example/eigen.ref

@ -0,0 +1,18 @@
fixed_r = OK
fixed_c = OK
pt_r(fixed_r) = OK
pt_c(fixed_c) = OK
pt_r(fixed_c) = OK
pt_c(fixed_r) = OK
dense_r = OK
dense_c = OK
pt_r(dense_r) = OK
pt_c(dense_c) = OK
pt_r(dense_c) = OK
pt_c(dense_r) = OK
sparse_r = OK
sparse_c = OK
pt_r(sparse_r) = OK
pt_c(sparse_c) = OK
pt_r(sparse_c) = OK
pt_c(sparse_r) = OK

12
stormpy/resources/pybind11/example/example.cpp

@ -1,7 +1,7 @@
/*
example/example.cpp -- pybind example plugin
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -25,8 +25,13 @@ void init_ex13(py::module &);
void init_ex14(py::module &);
void init_ex15(py::module &);
void init_ex16(py::module &);
void init_ex17(py::module &);
void init_issues(py::module &);
#if defined(PYBIND11_TEST_EIGEN)
void init_eigen(py::module &);
#endif
PYBIND11_PLUGIN(example) {
py::module m("example", "pybind example plugin");
@ -46,7 +51,12 @@ PYBIND11_PLUGIN(example) {
init_ex14(m);
init_ex15(m);
init_ex16(m);
init_ex17(m);
init_issues(m);
#if defined(PYBIND11_TEST_EIGEN)
init_eigen(m);
#endif
return m.ptr();
}

2
stormpy/resources/pybind11/example/example1.cpp

@ -2,7 +2,7 @@
example/example1.cpp -- constructors, deconstructors, attribute access,
__str__, argument and return value conventions
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

4
stormpy/resources/pybind11/example/example1.ref

@ -7,8 +7,8 @@ Called Example1 destructor (32)
Instance 1: Example1[value=320]
Instance 2: Example1[value=32]
Called Example1 copy constructor with value 320..
Called Example1 copy constructor with value 320..
Called Example1 destructor (320)
Called Example1 move constructor with value 320..
Called Example1 destructor (0)
Example1[value=320]
Called Example1 destructor (320)
Example1[value=320]

7
stormpy/resources/pybind11/example/example10.cpp

@ -2,7 +2,7 @@
example/example10.cpp -- auto-vectorize functions over NumPy array
arguments
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -33,4 +33,9 @@ void init_ex10(py::module &m) {
// Vectorize a complex-valued function
m.def("vectorized_func3", py::vectorize(my_func3));
/// Numpy function which only accepts specific data types
m.def("selective_func", [](py::array_t<int, py::array::c_style>) { std::cout << "Int branch taken. "<< std::endl; });
m.def("selective_func", [](py::array_t<float, py::array::c_style>) { std::cout << "Float branch taken. "<< std::endl; });
m.def("selective_func", [](py::array_t<std::complex<float>, py::array::c_style>) { std::cout << "Complex float branch taken. "<< std::endl; });
}

5
stormpy/resources/pybind11/example/example10.py

@ -27,3 +27,8 @@ for f in [vectorized_func, vectorized_func2]:
print(f(np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2))
print(np.array([[1, 2, 3], [4, 5, 6]])* np.array([[2], [3]])* 2)
from example import selective_func
selective_func(np.array([1], dtype=np.int32))
selective_func(np.array([1.0], dtype=np.float32))
selective_func(np.array([1.0j], dtype=np.complex64))

3
stormpy/resources/pybind11/example/example10.ref

@ -73,3 +73,6 @@ my_func(x:int=6, y:float=3, z:float=2)
[ 24. 30. 36.]]
[[ 4 8 12]
[24 30 36]]
Int branch taken.
Float branch taken.
Complex float branch taken.

27
stormpy/resources/pybind11/example/example11.cpp

@ -1,7 +1,7 @@
/*
example/example11.cpp -- keyword arguments and default values
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -19,6 +19,27 @@ void kw_func4(const std::vector<int> &entries) {
std::cout << endl;
}
py::object call_kw_func(py::function f) {
py::tuple args = py::make_tuple(1234);
py::dict kwargs;
kwargs["y"] = py::cast(5678);
return f(*args, **kwargs);
}
void args_function(py::args args) {
for (size_t it=0; it<args.size(); ++it)
std::cout << "got argument: " << py::object(args[it]) << std::endl;
}
void args_kwargs_function(py::args args, py::kwargs kwargs) {
for (auto item : args)
std::cout << "got argument: " << item << std::endl;
if (kwargs) {
for (auto item : kwargs)
std::cout << "got keyword argument: " << item.first << " -> " << item.second << std::endl;
}
}
void init_ex11(py::module &m) {
m.def("kw_func", &kw_func, py::arg("x"), py::arg("y"));
m.def("kw_func2", &kw_func, py::arg("x") = 100, py::arg("y") = 200);
@ -30,4 +51,8 @@ void init_ex11(py::module &m) {
list.push_back(17);
m.def("kw_func4", &kw_func4, py::arg("myList") = list);
m.def("call_kw_func", &call_kw_func);
m.def("args_function", &args_function);
m.def("args_kwargs_function", &args_kwargs_function);
}

10
stormpy/resources/pybind11/example/example11.py

@ -5,7 +5,8 @@ import pydoc
sys.path.append('.')
from example import kw_func, kw_func2, kw_func3, kw_func4
from example import kw_func, kw_func2, kw_func3, kw_func4, call_kw_func
from example import args_function, args_kwargs_function
print(pydoc.render_doc(kw_func, "Help on %s"))
print(pydoc.render_doc(kw_func2, "Help on %s"))
@ -32,4 +33,9 @@ except Exception as e:
print("Caught expected exception: " + str(e))
kw_func4()
kw_func4(myList = [1, 2, 3])
kw_func4(myList=[1, 2, 3])
call_kw_func(kw_func2)
args_function('arg1_value', 'arg2_value', 3)
args_kwargs_function('arg1_value', 'arg2_value', arg3='arg3_value', arg4=4)

10
stormpy/resources/pybind11/example/example11.ref

@ -29,6 +29,14 @@ kw_func(x=5, y=10)
kw_func(x=5, y=10)
Caught expected exception: Incompatible function arguments. The following argument types are supported:
1. (x : int = 100L, y : int = 200L) -> NoneType
Invoked with:
kw_func4: 13 17
kw_func4: 1 2 3
kw_func(x=1234, y=5678)
got argument: arg1_value
got argument: arg2_value
got argument: 3
got argument: arg1_value
got argument: arg2_value
got keyword argument: arg3 -> arg3_value
got keyword argument: arg4 -> 4

18
stormpy/resources/pybind11/example/example12.cpp

@ -1,7 +1,7 @@
/*
example/example12.cpp -- overriding virtual functions from Python
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -50,19 +50,21 @@ public:
virtual bool run_bool() {
PYBIND11_OVERLOAD_PURE(
bool,
Example12,
run_bool
bool, /* Return type */
Example12, /* Parent class */
run_bool, /* Name of function */
/* This function has no arguments. The trailing comma
in the previous line is needed for some compilers */
);
throw std::runtime_error("this will never be reached");
}
virtual void pure_virtual() {
PYBIND11_OVERLOAD_PURE(
void, /* Return type */
Example12, /* Parent class */
pure_virtual /* Name of function */
/* This function has no arguments */
pure_virtual, /* Name of function */
/* This function has no arguments. The trailing comma
in the previous line is needed for some compilers */
);
}
};
@ -87,6 +89,8 @@ void init_ex12(py::module &m) {
/* Declare that 'PyExample12' is really an alias for the original type 'Example12' */
.alias<Example12>()
.def(py::init<int>())
/* Copy constructor (not needed in this case, but should generally be declared in this way) */
.def(py::init<const PyExample12 &>())
/* Reference original class in function definitions */
.def("run", &Example12::run)
.def("run_bool", &Example12::run_bool)

2
stormpy/resources/pybind11/example/example12.ref

@ -1,7 +1,7 @@
Constructing Example12..
Original implementation of Example12::run(state=10, value=20)
30
Caught expected exception: Tried to call pure virtual function "pure_virtual"
Caught expected exception: Tried to call pure virtual function "Example12::pure_virtual"
Constructing Example12..
ExtendedExample12::run(20), calling parent..
Original implementation of Example12::run(state=11, value=21)

2
stormpy/resources/pybind11/example/example13.cpp

@ -2,7 +2,7 @@
example/example13.cpp -- keep_alive modifier (pybind11's version
of Boost.Python's with_custodian_and_ward / with_custodian_and_ward_postcall)
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

50
stormpy/resources/pybind11/example/example14.cpp

@ -1,7 +1,7 @@
/*
example/example14.cpp -- opaque types, passing void pointers
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -13,24 +13,46 @@
typedef std::vector<std::string> StringList;
class ClassWithSTLVecProperty {
public:
StringList stringList;
};
/* IMPORTANT: Disable internal pybind11 translation mechanisms for STL data structures */
PYBIND11_MAKE_OPAQUE(StringList);
void init_ex14(py::module &m) {
py::class_<py::opaque<StringList>>(m, "StringList")
py::class_<StringList>(m, "StringList")
.def(py::init<>())
.def("pop_back", &StringList::pop_back)
/* There are multiple versions of push_back(), etc. Select the right ones. */
.def("push_back", (void (StringList::*)(const std::string &)) &StringList::push_back)
.def("back", (std::string &(StringList::*)()) &StringList::back)
.def("__len__", [](const StringList &v) { return v.size(); })
.def("__iter__", [](StringList &v) {
return py::make_iterator(v.begin(), v.end());
}, py::keep_alive<0, 1>());
py::class_<ClassWithSTLVecProperty>(m, "ClassWithSTLVecProperty")
.def(py::init<>())
.def("push_back", [](py::opaque<StringList> &l, const std::string &str) { l->push_back(str); })
.def("pop_back", [](py::opaque<StringList> &l) { l->pop_back(); })
.def("back", [](py::opaque<StringList> &l) { return l->back(); });
m.def("print_opaque_list", [](py::opaque<StringList> &_l) {
StringList &l = _l;
std::cout << "Opaque list: " << std::endl;
for (auto entry : l)
std::cout << " " << entry << std::endl;
.def_readwrite("stringList", &ClassWithSTLVecProperty::stringList);
m.def("print_opaque_list", [](const StringList &l) {
std::cout << "Opaque list: [";
bool first = true;
for (auto entry : l) {
if (!first)
std::cout << ", ";
std::cout << entry;
first = false;
}
std::cout << "]" << std::endl;
});
m.def("return_void_ptr", []() { return (void *) 1234; });
m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : " << (uint64_t) ptr << std::endl; });
m.def("return_void_ptr", []() { return (void *) 0x1234; });
m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : 0x" << std::hex << (uint64_t) ptr << std::endl; });
m.def("return_null_str", []() { return (char *) nullptr; });
m.def("print_null_str", [](char *ptr) { std::cout << "Got null str : " << (uint64_t) ptr << std::endl; });
m.def("print_null_str", [](char *ptr) { std::cout << "Got null str : 0x" << std::hex << (uint64_t) ptr << std::endl; });
m.def("return_unique_ptr", []() -> std::unique_ptr<StringList> {
StringList *result = new StringList();

28
stormpy/resources/pybind11/example/example14.py

@ -4,21 +4,47 @@ import sys
sys.path.append('.')
from example import StringList, print_opaque_list
from example import ClassWithSTLVecProperty
from example import return_void_ptr, print_void_ptr
from example import return_null_str, print_null_str
from example import return_unique_ptr
from example import Example1
#####
l = StringList()
l.push_back("Element 1")
l.push_back("Element 2")
print_opaque_list(l)
print("Back element is %s" % l.back())
for i, k in enumerate(l):
print("%i/%i : %s" % (i + 1, len(l), k))
l.pop_back()
print_opaque_list(l)
#####
cvp = ClassWithSTLVecProperty()
print_opaque_list(cvp.stringList)
cvp.stringList = l
cvp.stringList.push_back("Element 3")
print_opaque_list(cvp.stringList)
#####
print_void_ptr(return_void_ptr())
print_void_ptr(Example1()) # Should also work for other C++ types
try:
print_void_ptr([1, 2, 3]) # This should not work
except Exception as e:
print("Caught expected exception: " + str(e))
print(return_null_str())
print_null_str(return_null_str())
print(return_unique_ptr())
#####
ptr = return_unique_ptr()
print(ptr)
print_opaque_list(ptr)

24
stormpy/resources/pybind11/example/example14.ref

@ -1,10 +1,18 @@
Opaque list:
Element 1
Element 2
Opaque list: [Element 1, Element 2]
Back element is Element 2
Opaque list:
Element 1
Got void ptr : 1234
1/2 : Element 1
2/2 : Element 2
Opaque list: [Element 1]
Opaque list: []
Opaque list: [Element 1, Element 3]
Got void ptr : 0x1234
Called Example1 default constructor..
Got void ptr : 0x7f9ba0f3c430
Called Example1 destructor (0)
Caught expected exception: Incompatible function arguments. The following argument types are supported:
1. (capsule) -> NoneType
Invoked with: [1, 2, 3]
None
Got null str : 0
[u'some value']
Got null str : 0x0
<example.StringList object at 0x10d3277a0>
Opaque list: [some value]

2
stormpy/resources/pybind11/example/example15.cpp

@ -1,7 +1,7 @@
/*
example/example15.cpp -- pickle support
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

2
stormpy/resources/pybind11/example/example15.py

@ -14,7 +14,7 @@ p = Pickleable("test_value")
p.setExtra1(15)
p.setExtra2(48)
data = pickle.dumps(p, -1) # -1 is important (use highest protocol version)
data = pickle.dumps(p, 2) # Must use pickle protocol >= 2
print("%s %i %i" % (p.value(), p.extra1(), p.extra2()))
p2 = pickle.loads(data)

2
stormpy/resources/pybind11/example/example16.cpp

@ -1,7 +1,7 @@
/*
example/example16.cpp -- automatic upcasting for polymorphic types
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

36
stormpy/resources/pybind11/example/example17.cpp

@ -0,0 +1,36 @@
/*
example/example17.cpp -- Usage of stl_binders functions
Copyright (c) 2016 Sergey Lyskov
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
#include <pybind11/stl_bind.h>
class El {
public:
El() = delete;
El(int v) : a(v) { }
int a;
};
std::ostream & operator<<(std::ostream &s, El const&v) {
s << "El{" << v.a << '}';
return s;
}
void init_ex17(py::module &m) {
pybind11::class_<El>(m, "El")
.def(pybind11::init<int>());
pybind11::bind_vector<unsigned int>(m, "VectorInt");
pybind11::bind_vector<El>(m, "VectorEl");
pybind11::bind_vector<std::vector<El>>(m, "VectorVectorEl");
}

40
stormpy/resources/pybind11/example/example17.py

@ -0,0 +1,40 @@
#!/usr/bin/env python
from __future__ import print_function
from example import VectorInt, El, VectorEl, VectorVectorEl
v_int = VectorInt([0, 0])
print(len(v_int))
print(bool(v_int))
v_int2 = VectorInt([0, 0])
print(v_int == v_int2)
v_int2[1] = 1
print(v_int != v_int2)
v_int2.append(2)
v_int2.append(3)
v_int2.insert(0, 1)
v_int2.insert(0, 2)
v_int2.insert(0, 3)
print(v_int2)
v_int.append(99)
v_int2[2:-2] = v_int
print(v_int2)
del v_int2[1:3]
print(v_int2)
del v_int2[0]
print(v_int2)
v_a = VectorEl()
v_a.append(El(1))
v_a.append(El(2))
print(v_a)
vv_a = VectorVectorEl()
vv_a.append(v_a)
vv_b = vv_a[0]
print(vv_b)

10
stormpy/resources/pybind11/example/example17.ref

@ -0,0 +1,10 @@
2
True
True
True
VectorInt[3, 2, 1, 0, 1, 2, 3]
VectorInt[3, 2, 0, 0, 99, 2, 3]
VectorInt[3, 0, 99, 2, 3]
VectorInt[0, 99, 2, 3]
VectorEl[El{1}, El{2}]
VectorEl[El{1}, El{2}]

2
stormpy/resources/pybind11/example/example2.cpp

@ -2,7 +2,7 @@
example/example2.cpp2 -- singleton design pattern, static functions and
variables, passing and interacting with Python types
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

2
stormpy/resources/pybind11/example/example3.cpp

@ -1,7 +1,7 @@
/*
example/example3.cpp -- operator overloading
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

20
stormpy/resources/pybind11/example/example3.ref

@ -3,52 +3,52 @@ Value constructor
v1 = [1.000000, 2.000000]
v2 = [3.000000, -1.000000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
v1+v2 = [4.000000, 1.000000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
v1-v2 = [-2.000000, 3.000000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
v1-8 = [-7.000000, -6.000000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
v1+8 = [9.000000, 10.000000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
v1*8 = [8.000000, 16.000000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
v1/8 = [0.125000, 0.250000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
8-v1 = [7.000000, 6.000000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
8+v1 = [9.000000, 10.000000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
8*v1 = [8.000000, 16.000000]
Value constructor
Copy constructor
Move constructor
Destructor.
Destructor.
8/v1 = [8.000000, 4.000000]

2
stormpy/resources/pybind11/example/example4.cpp

@ -1,7 +1,7 @@
/*
example/example4.cpp -- global constants and functions, enumerations, raw byte strings
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

6
stormpy/resources/pybind11/example/example5.cpp

@ -2,7 +2,7 @@
example/example5.cpp -- inheritance, callbacks, acquiring and releasing the
global interpreter lock
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -43,12 +43,12 @@ void dog_bark(const Dog &dog) {
}
bool test_callback1(py::object func) {
func.call();
func();
return false;
}
int test_callback2(py::object func) {
py::object result = func.call("Hello", 'x', true, 5);
py::object result = func("Hello", 'x', true, 5);
return result.cast<int>();
}

2
stormpy/resources/pybind11/example/example5.ref

@ -14,7 +14,7 @@ Polly is a parrot
Molly is a dog
The following error is expected: Incompatible function arguments. The following argument types are supported:
1. (example.Dog) -> NoneType
Invoked with: <Pet object at 0>
Callback function 1 called!
False
Callback function 2 called : Hello, x, True, 5

2
stormpy/resources/pybind11/example/example6.cpp

@ -2,7 +2,7 @@
example/example6.cpp -- supporting Pythons' sequence protocol, iterators,
etc.
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

6
stormpy/resources/pybind11/example/example6.ref

@ -1,13 +1,13 @@
Value constructor: Creating a sequence with 5 entries
s = <example.Sequence object at 0x1033bd8d0>
s = <example.Sequence object at 0x10c786c70>
len(s) = 5
s[0], s[3] = 0.000000 0.000000
12.34 in s: False
12.34 in s: True
s[0], s[3] = 12.340000 56.779999
Value constructor: Creating a sequence with 5 entries
Copy constructor: Creating a sequence with 5 entries
Freeing a sequence with 5 entries
Move constructor: Creating a sequence with 5 entries
Freeing a sequence with 0 entries
Value constructor: Creating a sequence with 5 entries
rev[0], rev[1], rev[2], rev[3], rev[4] = 0.000000 56.779999 0.000000 0.000000 12.340000
0.0 56.7799987793 0.0 0.0 12.3400001526

16
stormpy/resources/pybind11/example/example7.cpp

@ -1,7 +1,7 @@
/*
example/example7.cpp -- supporting Pythons' buffer protocol
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -80,7 +80,7 @@ void init_ex7(py::module &m) {
/// Construct from a buffer
.def("__init__", [](Matrix &v, py::buffer b) {
py::buffer_info info = b.request();
if (info.format != py::format_descriptor<float>::value() || info.ndim != 2)
if (info.format != py::format_descriptor<float>::value || info.ndim != 2)
throw std::runtime_error("Incompatible buffer format!");
new (&v) Matrix(info.shape[0], info.shape[1]);
memcpy(v.data(), info.ptr, sizeof(float) * v.rows() * v.cols());
@ -103,12 +103,12 @@ void init_ex7(py::module &m) {
/// Provide buffer access
.def_buffer([](Matrix &m) -> py::buffer_info {
return py::buffer_info(
m.data(), /* Pointer to buffer */
sizeof(float), /* Size of one scalar */
py::format_descriptor<float>::value(), /* Python struct-style format descriptor */
2, /* Number of dimensions */
{ m.rows(), m.cols() }, /* Buffer dimensions */
{ sizeof(float) * m.rows(), /* Strides (in bytes) for each index */
m.data(), /* Pointer to buffer */
sizeof(float), /* Size of one scalar */
py::format_descriptor<float>::value, /* Python struct-style format descriptor */
2, /* Number of dimensions */
{ m.rows(), m.cols() }, /* Buffer dimensions */
{ sizeof(float) * m.rows(), /* Strides (in bytes) for each index */
sizeof(float) }
);
});

2
stormpy/resources/pybind11/example/example8.cpp

@ -2,7 +2,7 @@
example/example8.cpp -- binding classes with custom reference counting,
implicit conversions between types
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

2
stormpy/resources/pybind11/example/example9.cpp

@ -2,7 +2,7 @@
example/example9.cpp -- nested modules, importing modules, and
internal references
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

108
stormpy/resources/pybind11/example/issues.cpp

@ -1,36 +1,30 @@
/*
example/issues.cpp -- collection of testcases for miscellaneous issues
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
#include <pybind11/stl.h>
struct Base {
virtual void dispatch(void) const = 0;
};
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);
struct DispatchIssue : Base {
virtual void dispatch(void) const {
PYBIND11_OVERLOAD_PURE(void, Base, dispatch);
}
};
void dispatch_issue_go(const Base * b) { b->dispatch(); }
PYBIND11_PLUGIN(mytest)
{
pybind11::module m("mytest", "A test");
return m.ptr();
}
void init_issues(py::module &m) {
py::module m2 = m.def_submodule("issues");
#if !defined(_MSC_VER)
// Visual Studio 2015 currently cannot compile this test
// (see the comment in type_caster_base::make_copy_constructor)
// #70 compilation issue if operator new is not public
class NonConstructible { private: void *operator new(size_t bytes) throw(); };
py::class_<NonConstructible>(m, "Foo");
m2.def("getstmt", []() -> NonConstructible * { return nullptr; },
py::return_value_policy::reference);
#endif
// #137: const char* isn't handled properly
m2.def("print_cchar", [](const char *string) { std::cout << string << std::endl; });
@ -38,10 +32,80 @@ void init_issues(py::module &m) {
m2.def("print_char", [](char c) { std::cout << c << std::endl; });
// #159: virtual function dispatch has problems with similar-named functions
pybind11::class_<DispatchIssue> base(m2, "DispatchIssue");
struct Base { virtual void dispatch(void) const {
/* for some reason MSVC2015 can't compile this if the function is pure virtual */
}; };
struct DispatchIssue : Base {
virtual void dispatch(void) const {
PYBIND11_OVERLOAD_PURE(void, Base, dispatch, /* no arguments */);
}
};
py::class_<DispatchIssue> base(m2, "DispatchIssue");
base.alias<Base>()
.def(pybind11::init<>())
.def(py::init<>())
.def("dispatch", &Base::dispatch);
m2.def("dispatch_issue_go", &dispatch_issue_go);
m2.def("dispatch_issue_go", [](const Base * b) { b->dispatch(); });
struct Placeholder { int i; Placeholder(int i) : i(i) { } };
py::class_<Placeholder>(m2, "Placeholder")
.def(py::init<int>())
.def("__repr__", [](const Placeholder &p) { return "Placeholder[" + std::to_string(p.i) + "]"; });
// #171: Can't return reference wrappers (or STL datastructures containing them)
m2.def("return_vec_of_reference_wrapper", [](std::reference_wrapper<Placeholder> p4){
Placeholder *p1 = new Placeholder{1};
Placeholder *p2 = new Placeholder{2};
Placeholder *p3 = new Placeholder{3};
std::vector<std::reference_wrapper<Placeholder>> v;
v.push_back(std::ref(*p1));
v.push_back(std::ref(*p2));
v.push_back(std::ref(*p3));
v.push_back(p4);
return v;
});
// #181: iterator passthrough did not compile
m2.def("iterator_passthrough", [](py::iterator s) -> py::iterator {
return py::make_iterator(std::begin(s), std::end(s));
});
// #187: issue involving std::shared_ptr<> return value policy & garbage collection
struct ElementBase { virtual void foo() { } /* Force creation of virtual table */ };
struct ElementA : ElementBase {
ElementA(int v) : v(v) { }
int value() { return v; }
int v;
};
struct ElementList {
void add(std::shared_ptr<ElementBase> e) { l.push_back(e); }
std::vector<std::shared_ptr<ElementBase>> l;
};
py::class_<ElementBase, std::shared_ptr<ElementBase>> (m2, "ElementBase");
py::class_<ElementA, std::shared_ptr<ElementA>>(m2, "ElementA", py::base<ElementBase>())
.def(py::init<int>())
.def("value", &ElementA::value);
py::class_<ElementList, std::shared_ptr<ElementList>>(m2, "ElementList")
.def(py::init<>())
.def("add", &ElementList::add)
.def("get", [](ElementList &el){
py::list list;
for (auto &e : el.l)
list.append(py::cast(e));
return list;
});
// (no id): should not be able to pass 'None' to a reference argument
m2.def("print_element", [](ElementA &el) { std::cout << el.value() << std::endl; });
// (no id): don't cast doubles to ints
m2.def("expect_float", [](float f) { return f; });
m2.def("expect_int", [](int i) { return i; });
}

29
stormpy/resources/pybind11/example/issues.py

@ -5,6 +5,11 @@ sys.path.append('.')
from example.issues import print_cchar, print_char
from example.issues import DispatchIssue, dispatch_issue_go
from example.issues import Placeholder, return_vec_of_reference_wrapper
from example.issues import iterator_passthrough
from example.issues import ElementList, ElementA, print_element
from example.issues import expect_float, expect_int
import gc
print_cchar("const char *")
print_char('c')
@ -26,3 +31,27 @@ class PyClass2(DispatchIssue):
b = PyClass2()
dispatch_issue_go(b)
print(return_vec_of_reference_wrapper(Placeholder(4)))
print(list(iterator_passthrough(iter([3, 5, 7, 9, 11, 13, 15]))))
el = ElementList()
for i in range(10):
el.add(ElementA(i))
gc.collect()
for i, v in enumerate(el.get()):
print("%i==%i, " % (i, v.value()), end='')
print()
try:
print_element(None)
except Exception as e:
print("Failed as expected: " + str(e))
try:
print(expect_int(5.2))
except Exception as e:
print("Failed as expected: " + str(e))
print(expect_float(12))

12
stormpy/resources/pybind11/example/issues.ref

@ -1,4 +1,14 @@
const char *
c
Failed as expected: Tried to call pure virtual function "dispatch"
Failed as expected: Tried to call pure virtual function "Base::dispatch"
Yay..
[Placeholder[1], Placeholder[2], Placeholder[3], Placeholder[4]]
[3, 5, 7, 9, 11, 13, 15]
0==0, 1==1, 2==2, 3==3, 4==4, 5==5, 6==6, 7==7, 8==8, 9==9,
Failed as expected: Incompatible function arguments. The following argument types are supported:
1. (example.issues.ElementA) -> NoneType
Invoked with: None
Failed as expected: Incompatible function arguments. The following argument types are supported:
1. (int) -> int
Invoked with: 5.2
12.0

19
stormpy/resources/pybind11/include/pybind11/attr.h

@ -2,7 +2,7 @@
pybind11/pybind11.h: Infrastructure for processing custom
type and function attributes
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -92,19 +92,28 @@ struct function_record {
std::vector<argument_record> args;
/// Pointer to lambda function which converts arguments and performs the actual call
handle (*impl) (function_record *, handle, handle) = nullptr;
handle (*impl) (function_record *, handle, handle, handle) = nullptr;
/// Storage for the wrapped function pointer and captured data, if any
void *data = nullptr;
void *data[3] = { };
/// Pointer to custom destructor for 'data' (if needed)
void (*free_data) (void *ptr) = nullptr;
void (*free_data) (function_record *ptr) = nullptr;
/// Return value policy associated with this function
return_value_policy policy = return_value_policy::automatic;
/// True if name == '__init__'
bool is_constructor = false;
bool is_constructor : 1;
/// True if the function has a '*args' argument
bool has_args : 1;
/// True if the function has a '**kwargs' argument
bool has_kwargs : 1;
/// Number of arguments
uint16_t nargs;
/// Python method object
PyMethodDef *def = nullptr;

263
stormpy/resources/pybind11/include/pybind11/cast.h

@ -2,7 +2,7 @@
pybind11/cast.h: Partial template specializations to cast between
C++ and Python types
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -15,23 +15,9 @@
#include "descr.h"
#include <array>
#include <limits>
#include <iostream>
NAMESPACE_BEGIN(pybind11)
/// Thin wrapper type used to treat certain data types as opaque (e.g. STL vectors, etc.)
template <typename Type> class opaque {
public:
template <typename... Args> opaque(Args&&... args) : value(std::forward<Args>(args)...) { }
operator Type&() { return value; }
operator const Type&() const { return value; }
operator Type*() { return &value; }
operator const Type*() const { return &value; }
Type* operator->() { return &value; }
const Type* operator->() const { return &value; }
private:
Type value;
};
NAMESPACE_BEGIN(detail)
/// Additional type information which does not fit into the PyTypeObject
@ -55,20 +41,30 @@ PYBIND11_NOINLINE inline internals &get_internals() {
internals_ptr = caps;
} else {
internals_ptr = new internals();
#if defined(WITH_THREAD)
PyEval_InitThreads();
PyThreadState *tstate = PyThreadState_Get();
internals_ptr->tstate = PyThread_create_key();
PyThread_set_key_value(internals_ptr->tstate, tstate);
internals_ptr->istate = tstate->interp;
#endif
builtins[id] = capsule(internals_ptr);
}
return *internals_ptr;
}
PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type) {
PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type, bool throw_if_missing = true) {
auto const &type_dict = get_internals().registered_types_py;
do {
auto it = type_dict.find(type);
if (it != type_dict.end())
return (detail::type_info *) it->second;
type = type->tp_base;
if (!type)
pybind11_fail("pybind11::detail::get_type_info: unable to find type object!");
if (!type) {
if (throw_if_missing)
pybind11_fail("pybind11::detail::get_type_info: unable to find type object!");
return nullptr;
}
} while (true);
}
@ -110,6 +106,18 @@ PYBIND11_NOINLINE inline handle get_object_handle(const void *ptr) {
return handle((PyObject *) it->second);
}
inline PyThreadState *get_thread_state_unchecked() {
#if PY_VERSION_HEX < 0x03000000
return _PyThreadState_Current;
#elif PY_VERSION_HEX < 0x03050000
return (PyThreadState*) _Py_atomic_load_relaxed(&_PyThreadState_Current);
#elif PY_VERSION_HEX < 0x03050200
return (PyThreadState*) _PyThreadState_Current.value;
#else
return _PyThreadState_UncheckedGet();
#endif
}
class type_caster_generic {
public:
PYBIND11_NOINLINE type_caster_generic(const std::type_info &type_info)
@ -139,6 +147,7 @@ public:
const std::type_info *type_info,
const std::type_info *type_info_backup,
void *(*copy_constructor)(const void *),
void *(*move_constructor)(const void *),
const void *existing_holder = nullptr) {
void *src = const_cast<void *>(_src);
if (src == nullptr)
@ -185,6 +194,12 @@ public:
wrapper->value = copy_constructor(wrapper->value);
if (wrapper->value == nullptr)
throw cast_error("return_value_policy = copy, but the object is non-copyable!");
} else if (policy == return_value_policy::move) {
wrapper->value = move_constructor(wrapper->value);
if (wrapper->value == nullptr)
wrapper->value = copy_constructor(wrapper->value);
if (wrapper->value == nullptr)
throw cast_error("return_value_policy = move, but the object is neither movable nor copyable!");
} else if (policy == return_value_policy::reference) {
wrapper->owned = false;
} else if (policy == return_value_policy::reference_internal) {
@ -207,16 +222,16 @@ protected:
/* Determine suitable casting operator */
template <typename T>
using cast_op_type = typename std::conditional<std::is_pointer<T>::value,
using cast_op_type = typename std::conditional<std::is_pointer<typename std::remove_reference<T>::type>::value,
typename std::add_pointer<typename intrinsic_type<T>::type>::type,
typename std::add_lvalue_reference<typename intrinsic_type<T>::type>::type>::type;
/// Generic type caster for objects stored on the heap
template <typename type, typename Enable = void> class type_caster : public type_caster_generic {
template <typename type> class type_caster_base : public type_caster_generic {
public:
static PYBIND11_DESCR name() { return type_descr(_<type>()); }
type_caster() : type_caster_generic(typeid(type)) { }
type_caster_base() : type_caster_generic(typeid(type)) { }
static handle cast(const type &src, return_value_policy policy, handle parent) {
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
@ -224,21 +239,55 @@ public:
return cast(&src, policy, parent);
}
static handle cast(type &&src, return_value_policy policy, handle parent) {
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
policy = return_value_policy::move;
return cast(&src, policy, parent);
}
static handle cast(const type *src, return_value_policy policy, handle parent) {
return type_caster_generic::cast(src, policy, parent, src ? &typeid(*src) : nullptr, &typeid(type), &copy_constructor);
return type_caster_generic::cast(
src, policy, parent, src ? &typeid(*src) : nullptr, &typeid(type),
make_copy_constructor(src), make_move_constructor(src));
}
template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
operator type*() { return (type *) value; }
operator type&() { return *((type *) value); }
operator type&() { if (!value) throw cast_error(); return *((type *) value); }
protected:
template <typename T = type, typename std::enable_if<detail::is_copy_constructible<T>::value, int>::type = 0>
static void *copy_constructor(const void *arg) {
return (void *) new type(*((const type *) arg));
typedef void *(*Constructor)(const void *stream);
#if !defined(_MSC_VER)
/* Only enabled when the types are {copy,move}-constructible *and* when the type
does not have a private operator new implementaton. */
template <typename T = type> static auto make_copy_constructor(const T *value) -> decltype(new T(*value), Constructor(nullptr)) {
return [](const void *arg) -> void * { return new T(*((const T *) arg)); }; }
template <typename T = type> static auto make_move_constructor(const T *value) -> decltype(new T(std::move(*((T *) value))), Constructor(nullptr)) {
return [](const void *arg) -> void * { return (void *) new T(std::move(*((T *) arg))); }; }
#else
/* Visual Studio 2015's SFINAE implementation doesn't yet handle the above robustly in all situations.
Use a workaround that only tests for constructibility for now. */
template <typename T = type, typename = typename std::enable_if<std::is_copy_constructible<T>::value>::type>
static Constructor make_copy_constructor(const T *value) {
return [](const void *arg) -> void * { return new T(*((const T *)arg)); }; }
template <typename T = type, typename = typename std::enable_if<std::is_move_constructible<T>::value>::type>
static Constructor make_move_constructor(const T *value) {
return [](const void *arg) -> void * { return (void *) new T(std::move(*((T *)arg))); }; }
#endif
static Constructor make_copy_constructor(...) { return nullptr; }
static Constructor make_move_constructor(...) { return nullptr; }
};
template <typename type, typename SFINAE = void> class type_caster : public type_caster_base<type> { };
template <typename type> class type_caster<std::reference_wrapper<type>> : public type_caster_base<type> {
public:
static handle cast(const std::reference_wrapper<type> &src, return_value_policy policy, handle parent) {
return type_caster_base<type>::cast(&src.get(), policy, parent);
}
template <typename T = type, typename std::enable_if<!detail::is_copy_constructible<T>::value, int>::type = 0>
static void *copy_constructor(const void *) { return nullptr; }
template <typename T> using cast_op_type = std::reference_wrapper<type>;
operator std::reference_wrapper<type>() { return std::ref(*((type *) this->value)); }
};
#define PYBIND11_TYPE_CASTER(type, py_name) \
@ -251,7 +300,7 @@ protected:
} \
operator type*() { return &value; } \
operator type&() { return value; } \
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>;
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>
#define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type) \
namespace pybind11 { namespace detail { \
@ -272,14 +321,20 @@ public:
bool load(handle src, bool) {
py_type py_value;
if (std::is_floating_point<T>::value) {
if (!src) {
return false;
} if (std::is_floating_point<T>::value) {
py_value = (py_type) PyFloat_AsDouble(src.ptr());
} else if (sizeof(T) <= sizeof(long)) {
if (PyFloat_Check(src.ptr()))
return false;
if (std::is_signed<T>::value)
py_value = (py_type) PyLong_AsLong(src.ptr());
else
py_value = (py_type) PyLong_AsUnsignedLong(src.ptr());
} else {
if (PyFloat_Check(src.ptr()))
return false;
if (std::is_signed<T>::value)
py_value = (py_type) PYBIND11_LONG_AS_LONGLONG(src.ptr());
else
@ -346,18 +401,31 @@ public:
using type_caster<void_type>::cast;
bool load(handle h, bool) {
if (h.ptr() == Py_None) {
if (!h) {
return false;
} else if (h.ptr() == Py_None) {
value = nullptr;
return true;
}
/* Check if this is a capsule */
capsule c(h, true);
if (!c.check())
return false;
value = (void *) c;
return true;
if (c.check()) {
value = (void *) c;
return true;
}
/* Check if this is a C++ type */
if (get_type_info((PyTypeObject *) h.get_type().ptr(), false)) {
value = ((instance<void> *) h.ptr())->value;
return true;
}
/* Fail */
return false;
}
static handle cast(void *ptr, return_value_policy /* policy */, handle /* parent */) {
static handle cast(const void *ptr, return_value_policy /* policy */, handle /* parent */) {
if (ptr)
return capsule(ptr).release();
else
@ -366,6 +434,7 @@ public:
template <typename T> using cast_op_type = void*&;
operator void *&() { return value; }
static PYBIND11_DESCR name() { return _("capsule"); }
private:
void *value = nullptr;
};
@ -375,7 +444,8 @@ template <> class type_caster<std::nullptr_t> : public type_caster<void_type> {
template <> class type_caster<bool> {
public:
bool load(handle src, bool) {
if (src.ptr() == Py_True) { value = true; return true; }
if (!src) return false;
else if (src.ptr() == Py_True) { value = true; return true; }
else if (src.ptr() == Py_False) { value = false; return true; }
else return false;
}
@ -390,7 +460,9 @@ public:
bool load(handle src, bool) {
object temp;
handle load_src = src;
if (PyUnicode_Check(load_src.ptr())) {
if (!src) {
return false;
} else if (PyUnicode_Check(load_src.ptr())) {
temp = object(PyUnicode_AsUTF8String(load_src.ptr()), false);
if (!temp) { PyErr_Clear(); return false; } // UnicodeEncodeError
load_src = temp;
@ -416,12 +488,12 @@ protected:
template <typename type> class type_caster<std::unique_ptr<type>> {
public:
static handle cast(std::unique_ptr<type> &&src, return_value_policy policy, handle parent) {
handle result = type_caster<type>::cast(src.get(), policy, parent);
handle result = type_caster_base<type>::cast(src.get(), policy, parent);
if (result)
src.release();
return result;
}
static PYBIND11_DESCR name() { return type_caster<type>::name(); }
static PYBIND11_DESCR name() { return type_caster_base<type>::name(); }
};
template <> class type_caster<std::wstring> {
@ -429,7 +501,9 @@ public:
bool load(handle src, bool) {
object temp;
handle load_src = src;
if (!PyUnicode_Check(load_src.ptr())) {
if (!src) {
return false;
} else if (!PyUnicode_Check(load_src.ptr())) {
temp = object(PyUnicode_FromObject(load_src.ptr()), false);
if (!temp) { PyErr_Clear(); return false; }
load_src = temp;
@ -467,7 +541,7 @@ protected:
template <> class type_caster<char> : public type_caster<std::string> {
public:
bool load(handle src, bool convert) {
if (src.ptr() == Py_None) { return true; }
if (src.ptr() == Py_None) return true;
return type_caster<std::string>::load(src, convert);
}
@ -490,7 +564,7 @@ public:
template <> class type_caster<wchar_t> : public type_caster<std::wstring> {
public:
bool load(handle src, bool convert) {
if (src.ptr() == Py_None) { return true; }
if (src.ptr() == Py_None) return true;
return type_caster<std::wstring>::load(src, convert);
}
@ -514,7 +588,9 @@ template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> {
typedef std::pair<T1, T2> type;
public:
bool load(handle src, bool convert) {
if (!PyTuple_Check(src.ptr()) || PyTuple_Size(src.ptr()) != 2)
if (!src)
return false;
else if (!PyTuple_Check(src.ptr()) || PyTuple_Size(src.ptr()) != 2)
return false;
return first.load(PyTuple_GET_ITEM(src.ptr(), 0), convert) &&
second.load(PyTuple_GET_ITEM(src.ptr(), 1), convert);
@ -550,13 +626,41 @@ protected:
template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
typedef std::tuple<Tuple...> type;
typedef std::tuple<typename intrinsic_type<Tuple>::type...> itype;
typedef std::tuple<args> args_type;
typedef std::tuple<args, kwargs> args_kwargs_type;
public:
enum { size = sizeof...(Tuple) };
static constexpr const bool has_kwargs = std::is_same<itype, args_kwargs_type>::value;
static constexpr const bool has_args = has_kwargs || std::is_same<itype, args_type>::value;
bool load(handle src, bool convert) {
if (!src || !PyTuple_Check(src.ptr()) || PyTuple_GET_SIZE(src.ptr()) != size)
return false;
return load(src, convert, typename make_index_sequence<sizeof...(Tuple)>::type());
}
template <typename T = itype, typename std::enable_if<
!std::is_same<T, args_type>::value &&
!std::is_same<T, args_kwargs_type>::value, int>::type = 0>
bool load_args(handle args, handle, bool convert) {
return load(args, convert, typename make_index_sequence<sizeof...(Tuple)>::type());
}
template <typename T = itype, typename std::enable_if<std::is_same<T, args_type>::value, int>::type = 0>
bool load_args(handle args, handle, bool convert) {
std::get<0>(value).load(args, convert);
return true;
}
template <typename T = itype, typename std::enable_if<std::is_same<T, args_kwargs_type>::value, int>::type = 0>
bool load_args(handle args, handle kwargs, bool convert) {
std::get<0>(value).load(args, convert);
std::get<1>(value).load(kwargs, convert);
return true;
}
static handle cast(const type &src, return_value_policy policy, handle parent) {
return cast(src, policy, parent, typename make_index_sequence<size>::type());
}
@ -595,10 +699,8 @@ protected:
}
template <size_t ... Indices> bool load(handle src, bool convert, index_sequence<Indices...>) {
if (!PyTuple_Check(src.ptr()) || PyTuple_Size(src.ptr()) != size)
return false;
std::array<bool, size> success {{
(PyTuple_GET_ITEM(src.ptr(), Indices) != nullptr ? std::get<Indices>(value).load(PyTuple_GET_ITEM(src.ptr(), Indices), convert) : false)...
std::get<Indices>(value).load(PyTuple_GET_ITEM(src.ptr(), Indices), convert)...
}};
(void) convert; /* avoid a warning when the tuple is empty */
for (bool r : success)
@ -627,13 +729,12 @@ protected:
};
/// Type caster for holder types like std::shared_ptr, etc.
template <typename type, typename holder_type> class type_caster_holder : public type_caster<type> {
template <typename type, typename holder_type> class type_caster_holder : public type_caster_base<type> {
public:
using type_caster<type>::cast;
using type_caster<type>::typeinfo;
using type_caster<type>::value;
using type_caster<type>::temp;
using type_caster<type>::copy_constructor;
using type_caster_base<type>::cast;
using type_caster_base<type>::typeinfo;
using type_caster_base<type>::value;
using type_caster_base<type>::temp;
bool load(handle src, bool convert) {
if (!src || !typeinfo) {
@ -670,11 +771,11 @@ public:
explicit operator holder_type&() { return holder; }
#endif
static handle cast(const holder_type &src, return_value_policy policy, handle parent) {
static handle cast(const holder_type &src, return_value_policy, handle) {
return type_caster_generic::cast(
src.get(), policy, parent,
src.get(), return_value_policy::take_ownership, handle(),
src.get() ? &typeid(*src.get()) : nullptr, &typeid(type),
&copy_constructor, &src);
nullptr, nullptr, &src);
}
protected:
@ -683,14 +784,16 @@ protected:
template <typename T> struct handle_type_name { static PYBIND11_DESCR name() { return _<T>(); } };
template <> struct handle_type_name<bytes> { static PYBIND11_DESCR name() { return _(PYBIND11_BYTES_NAME); } };
template <> struct handle_type_name<args> { static PYBIND11_DESCR name() { return _("*args"); } };
template <> struct handle_type_name<kwargs> { static PYBIND11_DESCR name() { return _("**kwargs"); } };
template <typename type>
struct type_caster<type, typename std::enable_if<std::is_base_of<handle, type>::value>::type> {
public:
template <typename T = type, typename std::enable_if<std::is_same<T, handle>::value, int>::type = 0>
bool load(handle src, bool /* convert */) { value = src; return value.check(); }
template <typename T = type, typename std::enable_if<!std::is_base_of<object, T>::value, int>::type = 0>
bool load(handle src, bool /* convert */) { value = type(src); return value.check(); }
template <typename T = type, typename std::enable_if<!std::is_same<T, handle>::value, int>::type = 0>
template <typename T = type, typename std::enable_if<std::is_base_of<object, T>::value, int>::type = 0>
bool load(handle src, bool /* convert */) { value = type(src, true); return value.check(); }
static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) {
@ -701,14 +804,17 @@ public:
NAMESPACE_END(detail)
template <typename T> inline T cast(handle handle) {
detail::type_caster<typename detail::intrinsic_type<T>::type> conv;
template <typename T> T cast(handle handle) {
typedef detail::type_caster<typename detail::intrinsic_type<T>::type> type_caster;
type_caster conv;
if (!conv.load(handle, true))
throw cast_error("Unable to cast Python object to C++ type");
return (T) conv;
return conv.operator typename type_caster::template cast_op_type<T>();
}
template <typename T> inline object cast(const T &value, return_value_policy policy = return_value_policy::automatic_reference, handle parent = handle()) {
template <typename T> object cast(const T &value,
return_value_policy policy = return_value_policy::automatic_reference,
handle parent = handle()) {
if (policy == return_value_policy::automatic)
policy = std::is_pointer<T>::value ? return_value_policy::take_ownership : return_value_policy::copy;
else if (policy == return_value_policy::automatic_reference)
@ -716,11 +822,11 @@ template <typename T> inline object cast(const T &value, return_value_policy pol
return object(detail::type_caster<typename detail::intrinsic_type<T>::type>::cast(value, policy, parent), false);
}
template <typename T> inline T handle::cast() const { return pybind11::cast<T>(*this); }
template <typename T> T handle::cast() const { return pybind11::cast<T>(*this); }
template <> inline void handle::cast() const { return; }
template <return_value_policy policy = return_value_policy::automatic_reference,
typename... Args> inline tuple make_tuple(Args&&... args_) {
typename... Args> tuple make_tuple(Args&&... args_) {
const size_t size = sizeof...(Args);
std::array<object, size> args {
{ object(detail::type_caster<typename detail::intrinsic_type<Args>::type>::cast(
@ -736,7 +842,7 @@ template <return_value_policy policy = return_value_policy::automatic_reference,
return result;
}
template <typename... Args> inline object handle::call(Args&&... args) const {
template <typename... Args> object handle::operator()(Args&&... args) const {
tuple args_tuple = pybind11::make_tuple(std::forward<Args>(args)...);
object result(PyObject_CallObject(m_ptr, args_tuple.ptr()), false);
if (!result)
@ -744,4 +850,27 @@ template <typename... Args> inline object handle::call(Args&&... args) const {
return result;
}
template <typename... Args> object handle::call(Args &&... args) const {
return operator()(std::forward<Args>(args)...);
}
inline object handle::operator()(detail::args_proxy args) const {
object result(PyObject_CallObject(m_ptr, args.ptr()), false);
if (!result)
throw error_already_set();
return result;
}
inline object handle::operator()(detail::args_proxy args, detail::kwargs_proxy kwargs) const {
object result(PyObject_Call(m_ptr, args.ptr(), kwargs.ptr()), false);
if (!result)
throw error_already_set();
return result;
}
#define PYBIND11_MAKE_OPAQUE(Type) \
namespace pybind11 { namespace detail { \
template<> class type_caster<Type> : public type_caster_base<Type> { }; \
}}
NAMESPACE_END(pybind11)

146
stormpy/resources/pybind11/include/pybind11/common.h

@ -1,7 +1,7 @@
/*
pybind11/common.h -- Basic macros
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -31,7 +31,7 @@
#endif
#define PYBIND11_VERSION_MAJOR 1
#define PYBIND11_VERSION_MINOR 5
#define PYBIND11_VERSION_MINOR 8
/// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode
#if defined(_MSC_VER)
@ -39,13 +39,14 @@
# pragma warning(push)
# pragma warning(disable: 4510 4610 4512 4005)
# if _DEBUG
# define _DEBUG_MARKER
# define PYBIND11_DEBUG_MARKER
# undef _DEBUG
# endif
#endif
#include <Python.h>
#include <frameobject.h>
#include <pythread.h>
#ifdef isalnum
# undef isalnum
@ -58,10 +59,10 @@
#endif
#if defined(_MSC_VER)
# if defined(_DEBUG_MARKER)
# if defined(PYBIND11_DEBUG_MARKER)
# define _DEBUG
# undef _DEBUG_MARKER
#endif
# undef PYBIND11_DEBUG_MARKER
# endif
# pragma warning(pop)
#endif
@ -80,6 +81,7 @@
#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize
#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyBytes_AsStringAndSize
#define PYBIND11_BYTES_AS_STRING PyBytes_AsString
#define PYBIND11_BYTES_CHECK PyBytes_Check
#define PYBIND11_LONG_CHECK(o) PyLong_Check(o)
#define PYBIND11_LONG_AS_LONGLONG(o) PyLong_AsLongLong(o)
#define PYBIND11_LONG_AS_UNSIGNED_LONGLONG(o) PyLong_AsUnsignedLongLong(o)
@ -97,6 +99,7 @@
#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyString_FromStringAndSize
#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyString_AsStringAndSize
#define PYBIND11_BYTES_AS_STRING PyString_AsString
#define PYBIND11_BYTES_CHECK PyString_Check
#define PYBIND11_LONG_CHECK(o) (PyInt_Check(o) || PyLong_Check(o))
#define PYBIND11_LONG_AS_LONGLONG(o) (PyInt_Check(o) ? (long long) PyLong_AsLong(o) : PyLong_AsLongLong(o))
#define PYBIND11_LONG_AS_UNSIGNED_LONGLONG(o) (PyInt_Check(o) ? (unsigned long long) PyLong_AsUnsignedLong(o) : PyLong_AsUnsignedLongLong(o))
@ -109,6 +112,13 @@
extern "C" PYBIND11_EXPORT PyObject *init##name()
#endif
#if PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03050200
extern "C" {
struct _Py_atomic_address { void *value; };
PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current;
};
#endif
#define PYBIND11_TRY_NEXT_OVERLOAD ((PyObject *) 1) // special failure return code
#define PYBIND11_STRINGIFY(x) #x
#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x)
@ -127,39 +137,59 @@
} \
PyObject *pybind11_init()
NAMESPACE_BEGIN(pybind11)
typedef Py_ssize_t ssize_t;
/// Approach used to cast a previously unknown C++ instance into a Python object
enum class return_value_policy : int {
/** Automatic: copy objects returned as values and take ownership of objects
returned as pointers */
enum class return_value_policy : uint8_t {
/** This is the default return value policy, which falls back to the policy
return_value_policy::take_ownership when the return value is a pointer.
Otherwise, it uses return_value::move or return_value::copy for rvalue
and lvalue references, respectively. See below for a description of what
all of these different policies do. */
automatic = 0,
/** Automatic variant 2: copy objects returned as values and reference objects
returned as pointers */
/** As above, but use policy return_value_policy::reference when the return
value is a pointer. You probably won't need to use this. */
automatic_reference,
/** Reference the object and take ownership. Python will call the
destructor and delete operator when the reference count reaches zero */
/** Reference an existing object (i.e. do not create a new copy) and take
ownership. Python will call the destructor and delete operator when the
objects reference count reaches zero. Undefined behavior ensues when
the C++ side does the same.. */
take_ownership,
/** Reference the object, but do not take ownership (dangerous when C++ code
deletes it and Python still has a nonzero reference count) */
/** Create a new copy of the returned object, which will be owned by
Python. This policy is comparably safe because the lifetimes of the two
instances are decoupled. */
copy,
/** Use std::move to move the return value contents into a new instance
that will be owned by Python. This policy is comparably safe because the
lifetimes of the two instances (move source and destination) are
decoupled. */
move,
/** Reference an existing object, but do not take ownership. The C++ side
is responsible for managing the objects lifetime and deallocating it
when it is no longer used. Warning: undefined behavior will ensue when
the C++ side deletes an object that is still referenced and used by
Python. */
reference,
/** Reference the object, but do not take ownership. The object is considered
be owned by the C++ instance whose method or property returned it. The
Python object will increase the reference count of this 'parent' by 1 */
reference_internal,
/// Create a new copy of the returned object, which will be owned by Python
copy
};
/// Format strings for basic number types
template <typename type> struct format_descriptor { };
#define PYBIND11_DECL_FMT(t, n) template<> struct format_descriptor<t> { static std::string value() { return n; }; }
PYBIND11_DECL_FMT(int8_t, "b"); PYBIND11_DECL_FMT(uint8_t, "B"); PYBIND11_DECL_FMT(int16_t, "h"); PYBIND11_DECL_FMT(uint16_t, "H");
PYBIND11_DECL_FMT(int32_t, "i"); PYBIND11_DECL_FMT(uint32_t, "I"); PYBIND11_DECL_FMT(int64_t, "q"); PYBIND11_DECL_FMT(uint64_t, "Q");
PYBIND11_DECL_FMT(float, "f"); PYBIND11_DECL_FMT(double, "d"); PYBIND11_DECL_FMT(bool, "?");
/** This policy only applies to methods and properties. It references the
object without taking ownership similar to the above
return_value_policy::reference policy. In contrast to that policy, the
function or propertys implicit this argument (called the parent) is
considered to be the the owner of the return value (the child).
pybind11 then couples the lifetime of the parent to the child via a
reference relationship that ensures that the parent cannot be garbage
collected while Python is still using the child. More advanced
variations of this scheme are also possible using combinations of
return_value_policy::reference and the keep_alive call policy */
reference_internal
};
/// Information record describing a Python buffer object
struct buffer_info {
@ -171,6 +201,7 @@ struct buffer_info {
std::vector<size_t> shape; // Shape of the tensor (1 entry per dimension)
std::vector<size_t> strides; // Number of entries between adjacent entries (for each per dimension)
buffer_info() : ptr(nullptr), view(nullptr) {}
buffer_info(void *ptr, size_t itemsize, const std::string &format, int ndim,
const std::vector<size_t> &shape, const std::vector<size_t> &strides)
: ptr(ptr), itemsize(itemsize), size(1), format(format),
@ -197,6 +228,8 @@ private:
NAMESPACE_BEGIN(detail)
inline static constexpr int log2(size_t n, int k = 0) { return (n <= 1) ? k : log2(n >> 1, k + 1); }
inline std::string error_string();
/// Core part of the 'instance' type which POD (needed to be able to use 'offsetof')
@ -228,6 +261,10 @@ struct internals {
std::unordered_map<const void *, void*> registered_types_py; // PyTypeObject* -> type_info
std::unordered_map<const void *, void*> registered_instances; // void * -> PyObject*
std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache;
#if defined(WITH_THREAD)
int tstate = 0;
PyInterpreterState *istate = nullptr;
#endif
};
/// Return a reference to the current 'internals' information
@ -239,7 +276,7 @@ template<size_t N, size_t ...S> struct make_index_sequence : make_index_sequence
template<size_t ...S> struct make_index_sequence <0, S...> { typedef index_sequence<S...> type; };
/// Strip the class from a method type
template <typename T> struct remove_class {};
template <typename T> struct remove_class { };
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...)> { typedef R type(A...); };
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) const> { typedef R type(A...); };
@ -252,34 +289,37 @@ template <typename T> struct intrinsic_type<T&&> { typedef type
template <typename T, size_t N> struct intrinsic_type<const T[N]> { typedef typename intrinsic_type<T>::type type; };
template <typename T, size_t N> struct intrinsic_type<T[N]> { typedef typename intrinsic_type<T>::type type; };
/** \brief SFINAE helper class to check if a copy constructor is usable (in contrast to
* std::is_copy_constructible, this class also checks if the 'new' operator is accessible */
template <typename T> struct is_copy_constructible {
template <typename T2> static std::true_type test(decltype(new T2(std::declval<typename std::add_lvalue_reference<T2>::type>())) *);
template <typename T2> static std::false_type test(...);
static const bool value = std::is_same<std::true_type, decltype(test<T>(nullptr))>::value;
};
/// Helper type to replace 'void' in some expressions
struct void_type { };
/// to_string variant which also accepts strings
template <typename T> inline typename std::enable_if<!std::is_enum<T>::value, std::string>::type
to_string(const T &value) { return std::to_string(value); }
template <> inline std::string to_string(const std::string &value) { return value; }
template <typename T> inline typename std::enable_if<std::is_enum<T>::value, std::string>::type
to_string(T value) { return std::to_string((int) value); }
NAMESPACE_END(detail)
#define PYBIND11_RUNTIME_EXCEPTION(name) \
class name : public std::runtime_error { public: \
name(const std::string &w) : std::runtime_error(w) { }; \
name(const char *s) : std::runtime_error(s) { }; \
name() : std::runtime_error("") { } \
};
// C++ bindings of core Python exceptions
struct stop_iteration : public std::runtime_error { public: stop_iteration(const std::string &w="") : std::runtime_error(w) {} };
struct index_error : public std::runtime_error { public: index_error(const std::string &w="") : std::runtime_error(w) {} };
struct error_already_set : public std::runtime_error { public: error_already_set() : std::runtime_error(detail::error_string()) {} };
/// Thrown when pybind11::cast or handle::call fail due to a type casting error
struct cast_error : public std::runtime_error { public: cast_error(const std::string &w = "") : std::runtime_error(w) {} };
PYBIND11_NOINLINE inline void pybind11_fail(const char *reason) { throw std::runtime_error(reason); }
PYBIND11_NOINLINE inline void pybind11_fail(const std::string &reason) { throw std::runtime_error(reason); }
class error_already_set : public std::runtime_error { public: error_already_set() : std::runtime_error(detail::error_string()) {} };
PYBIND11_RUNTIME_EXCEPTION(stop_iteration)
PYBIND11_RUNTIME_EXCEPTION(index_error)
PYBIND11_RUNTIME_EXCEPTION(value_error)
PYBIND11_RUNTIME_EXCEPTION(cast_error) /// Thrown when pybind11::cast or handle::call fail due to a type casting error
[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const char *reason) { throw std::runtime_error(reason); }
[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const std::string &reason) { throw std::runtime_error(reason); }
/// Format strings for basic number types
#define PYBIND11_DECL_FMT(t, v) template<> struct format_descriptor<t> { static constexpr const char *value = v; }
template <typename T, typename SFINAE = void> struct format_descriptor { };
template <typename T> struct format_descriptor<T, typename std::enable_if<std::is_integral<T>::value>::type> {
static constexpr const char value[2] =
{ "bBhHiIqQ"[detail::log2(sizeof(T))*2 + (std::is_unsigned<T>::value ? 1 : 0)], '\0' };
};
template <typename T> constexpr const char format_descriptor<
T, typename std::enable_if<std::is_integral<T>::value>::type>::value[2];
PYBIND11_DECL_FMT(float, "f"); PYBIND11_DECL_FMT(double, "d"); PYBIND11_DECL_FMT(bool, "?");
NAMESPACE_END(pybind11)

4
stormpy/resources/pybind11/include/pybind11/complex.h

@ -1,7 +1,7 @@
/*
pybind11/complex.h: Complex number support
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -26,6 +26,8 @@ NAMESPACE_BEGIN(detail)
template <typename T> class type_caster<std::complex<T>> {
public:
bool load(handle src, bool) {
if (!src)
return false;
Py_complex result = PyComplex_AsCComplex(src.ptr());
if (result.real == -1.0 && PyErr_Occurred()) {
PyErr_Clear();

2
stormpy/resources/pybind11/include/pybind11/descr.h

@ -2,7 +2,7 @@
pybind11/descr.h: Helper type for concatenating type signatures
either at runtime (C++11) or compile time (C++14)
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

281
stormpy/resources/pybind11/include/pybind11/eigen.h

@ -0,0 +1,281 @@
/*
pybind11/eigen.h: Transparent conversion for dense and sparse Eigen matrices
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#pragma once
#include "numpy.h"
#include <Eigen/Core>
#include <Eigen/SparseCore>
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
#endif
NAMESPACE_BEGIN(pybind11)
NAMESPACE_BEGIN(detail)
template <typename T> class is_eigen_dense {
private:
template<typename Derived> static std::true_type test(const Eigen::DenseBase<Derived> &);
static std::false_type test(...);
public:
static constexpr bool value = decltype(test(std::declval<T>()))::value;
};
template <typename T> class is_eigen_sparse {
private:
template<typename Derived> static std::true_type test(const Eigen::SparseMatrixBase<Derived> &);
static std::false_type test(...);
public:
static constexpr bool value = decltype(test(std::declval<T>()))::value;
};
template<typename Type>
struct type_caster<Type, typename std::enable_if<is_eigen_dense<Type>::value>::type> {
typedef typename Type::Scalar Scalar;
static constexpr bool rowMajor = Type::Flags & Eigen::RowMajorBit;
static constexpr bool isVector = Type::IsVectorAtCompileTime;
bool load(handle src, bool) {
array_t<Scalar> buffer(src, true);
if (!buffer.check())
return false;
buffer_info info = buffer.request();
if (info.ndim == 1) {
typedef Eigen::Stride<Eigen::Dynamic, 0> Strides;
if (!isVector &&
!(Type::RowsAtCompileTime == Eigen::Dynamic &&
Type::ColsAtCompileTime == Eigen::Dynamic))
return false;
if (Type::SizeAtCompileTime != Eigen::Dynamic &&
info.shape[0] != (size_t) Type::SizeAtCompileTime)
return false;
auto strides = Strides(info.strides[0] / sizeof(Scalar), 0);
value = Eigen::Map<Type, 0, Strides>(
(Scalar *) info.ptr, info.shape[0], 1, strides);
} else if (info.ndim == 2) {
typedef Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic> Strides;
if ((Type::RowsAtCompileTime != Eigen::Dynamic && info.shape[0] != (size_t) Type::RowsAtCompileTime) ||
(Type::ColsAtCompileTime != Eigen::Dynamic && info.shape[1] != (size_t) Type::ColsAtCompileTime))
return false;
auto strides = Strides(
info.strides[rowMajor ? 0 : 1] / sizeof(Scalar),
info.strides[rowMajor ? 1 : 0] / sizeof(Scalar));
value = Eigen::Map<Type, 0, Strides>(
(Scalar *) info.ptr, info.shape[0], info.shape[1], strides);
} else {
return false;
}
return true;
}
static handle cast(const Type *src, return_value_policy policy, handle parent) {
return cast(*src, policy, parent);
}
static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
if (isVector) {
return array(buffer_info(
/* Pointer to buffer */
const_cast<Scalar *>(src.data()),
/* Size of one scalar */
sizeof(Scalar),
/* Python struct-style format descriptor */
format_descriptor<Scalar>::value,
/* Number of dimensions */
1,
/* Buffer dimensions */
{ (size_t) src.size() },
/* Strides (in bytes) for each index */
{ sizeof(Scalar) }
)).release();
} else {
return array(buffer_info(
/* Pointer to buffer */
const_cast<Scalar *>(src.data()),
/* Size of one scalar */
sizeof(Scalar),
/* Python struct-style format descriptor */
format_descriptor<Scalar>::value,
/* Number of dimensions */
isVector ? 1 : 2,
/* Buffer dimensions */
{ (size_t) src.rows(),
(size_t) src.cols() },
/* Strides (in bytes) for each index */
{ sizeof(Scalar) * (rowMajor ? src.cols() : 1),
sizeof(Scalar) * (rowMajor ? 1 : src.rows()) }
)).release();
}
}
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>;
static PYBIND11_DESCR name() {
return _("numpy.ndarray[dtype=") + npy_format_descriptor<Scalar>::name() +
_(", shape=(") + rows() + _(", ") + cols() + _(")]");
}
operator Type*() { return &value; }
operator Type&() { return value; }
protected:
template <typename T = Type, typename std::enable_if<T::RowsAtCompileTime == Eigen::Dynamic, int>::type = 0>
static PYBIND11_DESCR rows() { return _("m"); }
template <typename T = Type, typename std::enable_if<T::RowsAtCompileTime != Eigen::Dynamic, int>::type = 0>
static PYBIND11_DESCR rows() { return _<T::RowsAtCompileTime>(); }
template <typename T = Type, typename std::enable_if<T::ColsAtCompileTime == Eigen::Dynamic, int>::type = 0>
static PYBIND11_DESCR cols() { return _("n"); }
template <typename T = Type, typename std::enable_if<T::ColsAtCompileTime != Eigen::Dynamic, int>::type = 0>
static PYBIND11_DESCR cols() { return _<T::ColsAtCompileTime>(); }
protected:
Type value;
};
template<typename Type>
struct type_caster<Type, typename std::enable_if<is_eigen_sparse<Type>::value>::type> {
typedef typename Type::Scalar Scalar;
typedef typename std::remove_reference<decltype(*std::declval<Type>().outerIndexPtr())>::type StorageIndex;
typedef typename Type::Index Index;
static constexpr bool rowMajor = Type::Flags & Eigen::RowMajorBit;
bool load(handle src, bool) {
if (!src)
return false;
object obj(src, true);
object sparse_module = module::import("scipy.sparse");
object matrix_type = sparse_module.attr(
rowMajor ? "csr_matrix" : "csc_matrix");
if (obj.get_type() != matrix_type.ptr()) {
try {
obj = matrix_type(obj);
} catch (const error_already_set &) {
PyErr_Clear();
return false;
}
}
auto valuesArray = array_t<Scalar>((object) obj.attr("data"));
auto innerIndicesArray = array_t<StorageIndex>((object) obj.attr("indices"));
auto outerIndicesArray = array_t<StorageIndex>((object) obj.attr("indptr"));
auto shape = pybind11::tuple((pybind11::object) obj.attr("shape"));
auto nnz = obj.attr("nnz").cast<Index>();
if (!valuesArray.check() || !innerIndicesArray.check() ||
!outerIndicesArray.check())
return false;
buffer_info outerIndices = outerIndicesArray.request();
buffer_info innerIndices = innerIndicesArray.request();
buffer_info values = valuesArray.request();
value = Eigen::MappedSparseMatrix<Scalar, Type::Flags, StorageIndex>(
shape[0].cast<Index>(),
shape[1].cast<Index>(),
nnz,
static_cast<StorageIndex *>(outerIndices.ptr),
static_cast<StorageIndex *>(innerIndices.ptr),
static_cast<Scalar *>(values.ptr)
);
return true;
}
static handle cast(const Type *src, return_value_policy policy, handle parent) {
return cast(*src, policy, parent);
}
static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
const_cast<Type&>(src).makeCompressed();
object matrix_type = module::import("scipy.sparse").attr(
rowMajor ? "csr_matrix" : "csc_matrix");
array data(buffer_info(
// Pointer to buffer
const_cast<Scalar *>(src.valuePtr()),
// Size of one scalar
sizeof(Scalar),
// Python struct-style format descriptor
format_descriptor<Scalar>::value,
// Number of dimensions
1,
// Buffer dimensions
{ (size_t) src.nonZeros() },
// Strides
{ sizeof(Scalar) }
));
array outerIndices(buffer_info(
// Pointer to buffer
const_cast<StorageIndex *>(src.outerIndexPtr()),
// Size of one scalar
sizeof(StorageIndex),
// Python struct-style format descriptor
format_descriptor<StorageIndex>::value,
// Number of dimensions
1,
// Buffer dimensions
{ (size_t) (rowMajor ? src.rows() : src.cols()) + 1 },
// Strides
{ sizeof(StorageIndex) }
));
array innerIndices(buffer_info(
// Pointer to buffer
const_cast<StorageIndex *>(src.innerIndexPtr()),
// Size of one scalar
sizeof(StorageIndex),
// Python struct-style format descriptor
format_descriptor<StorageIndex>::value,
// Number of dimensions
1,
// Buffer dimensions
{ (size_t) src.nonZeros() },
// Strides
{ sizeof(StorageIndex) }
));
return matrix_type(
std::make_tuple(data, innerIndices, outerIndices),
std::make_pair(src.rows(), src.cols())
).release();
}
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>;
template <typename T = Type, typename std::enable_if<(T::Flags & Eigen::RowMajorBit) != 0, int>::type = 0>
static PYBIND11_DESCR name() { return _("scipy.sparse.csr_matrix[dtype=") + npy_format_descriptor<Scalar>::name() + _("]"); }
template <typename T = Type, typename std::enable_if<(T::Flags & Eigen::RowMajorBit) == 0, int>::type = 0>
static PYBIND11_DESCR name() { return _("scipy.sparse.csc_matrix[dtype=") + npy_format_descriptor<Scalar>::name() + _("]"); }
operator Type*() { return &value; }
operator Type&() { return value; }
protected:
Type value;
};
NAMESPACE_END(detail)
NAMESPACE_END(pybind11)
#if defined(_MSC_VER)
#pragma warning(pop)
#endif

8
stormpy/resources/pybind11/include/pybind11/functional.h

@ -1,7 +1,7 @@
/*
pybind11/functional.h: std::function<> support
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -17,6 +17,7 @@ NAMESPACE_BEGIN(detail)
template <typename Return, typename... Args> struct type_caster<std::function<Return(Args...)>> {
typedef std::function<Return(Args...)> type;
typedef typename std::conditional<std::is_same<Return, void>::value, void_type, Return>::type retval_type;
public:
bool load(handle src_, bool) {
src_ = detail::get_function(src_);
@ -24,7 +25,8 @@ public:
return false;
object src(src_, true);
value = [src](Args... args) -> Return {
object retval(src.call(std::move(args)...));
gil_scoped_acquire acq;
object retval(src(std::move(args)...));
/* Visual studio 2015 parser issue: need parentheses around this expression */
return (retval.template cast<Return>());
};
@ -38,7 +40,7 @@ public:
PYBIND11_TYPE_CASTER(type, _("function<") +
type_caster<std::tuple<Args...>>::name() + _(" -> ") +
type_caster<typename intrinsic_type<Return>::type>::name() +
type_caster<retval_type>::name() +
_(">"));
};

70
stormpy/resources/pybind11/include/pybind11/numpy.h

@ -1,7 +1,7 @@
/*
pybind11/numpy.h: Basic NumPy support, auto-vectorization support
pybind11/numpy.h: Basic NumPy support, vectorize() wrapper
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -20,8 +20,7 @@
#endif
NAMESPACE_BEGIN(pybind11)
template <typename type> struct npy_format_descriptor { };
namespace detail { template <typename type, typename SFINAE = void> struct npy_format_descriptor { }; }
class array : public buffer {
public:
@ -77,9 +76,15 @@ public:
PYBIND11_OBJECT_DEFAULT(array, buffer, lookup_api().PyArray_Check_)
enum {
c_style = API::NPY_C_CONTIGUOUS_,
f_style = API::NPY_F_CONTIGUOUS_,
forcecast = API::NPY_ARRAY_FORCECAST_
};
template <typename Type> array(size_t size, const Type *ptr) {
API& api = lookup_api();
PyObject *descr = api.PyArray_DescrFromType_(npy_format_descriptor<Type>::value);
PyObject *descr = api.PyArray_DescrFromType_(detail::npy_format_descriptor<Type>::value);
if (descr == nullptr)
pybind11_fail("NumPy: unsupported buffer format!");
Py_intptr_t shape = (Py_intptr_t) size;
@ -120,34 +125,49 @@ protected:
}
};
template <typename T> class array_t : public array {
template <typename T, int ExtraFlags = array::forcecast> class array_t : public array {
public:
PYBIND11_OBJECT_CVT(array_t, array, is_non_null, m_ptr = ensure(m_ptr));
array_t() : array() { }
array_t(const buffer_info& info) : array(info) {}
static bool is_non_null(PyObject *ptr) { return ptr != nullptr; }
static PyObject *ensure(PyObject *ptr) {
if (ptr == nullptr)
return nullptr;
API &api = lookup_api();
PyObject *descr = api.PyArray_DescrFromType_(npy_format_descriptor<T>::value);
PyObject *result = api.PyArray_FromAny_(
ptr, descr, 0, 0, API::NPY_C_CONTIGUOUS_ | API::NPY_ENSURE_ARRAY_
| API::NPY_ARRAY_FORCECAST_, nullptr);
PyObject *descr = api.PyArray_DescrFromType_(detail::npy_format_descriptor<T>::value);
PyObject *result = api.PyArray_FromAny_(ptr, descr, 0, 0, API::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr);
if (!result)
PyErr_Clear();
Py_DECREF(ptr);
return result;
}
};
#define DECL_FMT(t, n) template<> struct npy_format_descriptor<t> { enum { value = array::API::n }; }
DECL_FMT(int8_t, NPY_BYTE_); DECL_FMT(uint8_t, NPY_UBYTE_); DECL_FMT(int16_t, NPY_SHORT_);
DECL_FMT(uint16_t, NPY_USHORT_); DECL_FMT(int32_t, NPY_INT_); DECL_FMT(uint32_t, NPY_UINT_);
DECL_FMT(int64_t, NPY_LONGLONG_); DECL_FMT(uint64_t, NPY_ULONGLONG_); DECL_FMT(float, NPY_FLOAT_);
DECL_FMT(double, NPY_DOUBLE_); DECL_FMT(bool, NPY_BOOL_); DECL_FMT(std::complex<float>, NPY_CFLOAT_);
DECL_FMT(std::complex<double>, NPY_CDOUBLE_);
#undef DECL_FMT
NAMESPACE_BEGIN(detail)
template <typename T> struct npy_format_descriptor<T, typename std::enable_if<std::is_integral<T>::value>::type> {
private:
constexpr static const int values[8] = {
array::API::NPY_BYTE_, array::API::NPY_UBYTE_, array::API::NPY_SHORT_, array::API::NPY_USHORT_,
array::API::NPY_INT_, array::API::NPY_UINT_, array::API::NPY_LONGLONG_, array::API::NPY_ULONGLONG_ };
public:
enum { value = values[detail::log2(sizeof(T)) * 2 + (std::is_unsigned<T>::value ? 1 : 0)] };
template <typename T2 = T, typename std::enable_if<std::is_signed<T2>::value, int>::type = 0>
static PYBIND11_DESCR name() { return _("int") + _<sizeof(T)*8>(); }
template <typename T2 = T, typename std::enable_if<!std::is_signed<T2>::value, int>::type = 0>
static PYBIND11_DESCR name() { return _("uint") + _<sizeof(T)*8>(); }
};
template <typename T> constexpr const int npy_format_descriptor<
T, typename std::enable_if<std::is_integral<T>::value>::type>::values[8];
#define DECL_FMT(Type, NumPyName, Name) template<> struct npy_format_descriptor<Type> { \
enum { value = array::API::NumPyName }; \
static PYBIND11_DESCR name() { return _(Name); } }
DECL_FMT(float, NPY_FLOAT_, "float32"); DECL_FMT(double, NPY_DOUBLE_, "float64"); DECL_FMT(bool, NPY_BOOL_, "bool");
DECL_FMT(std::complex<float>, NPY_CFLOAT_, "complex64"); DECL_FMT(std::complex<double>, NPY_CDOUBLE_, "complex128");
#undef DECL_FMT
template <class T>
using array_iterator = typename std::add_pointer<T>::type;
@ -298,11 +318,11 @@ struct vectorize_helper {
template <typename T>
vectorize_helper(T&&f) : f(std::forward<T>(f)) { }
object operator()(array_t<Args>... args) {
object operator()(array_t<Args, array::c_style | array::forcecast>... args) {
return run(args..., typename make_index_sequence<sizeof...(Args)>::type());
}
template <size_t ... Index> object run(array_t<Args>&... args, index_sequence<Index...> index) {
template <size_t ... Index> object run(array_t<Args, array::c_style | array::forcecast>&... args, index_sequence<Index...> index) {
/* Request buffers from all parameters */
const size_t N = sizeof...(Args);
@ -312,7 +332,7 @@ struct vectorize_helper {
int ndim = 0;
std::vector<size_t> shape(0);
bool trivial_broadcast = broadcast(buffers, ndim, shape);
size_t size = 1;
std::vector<size_t> strides(ndim);
if (ndim > 0) {
@ -328,13 +348,13 @@ struct vectorize_helper {
return cast(f(*((Args *) buffers[Index].ptr)...));
array result(buffer_info(nullptr, sizeof(Return),
format_descriptor<Return>::value(),
format_descriptor<Return>::value,
ndim, shape, strides));
buffer_info buf = result.request();
Return *output = (Return *) buf.ptr;
if(trivial_broadcast) {
if (trivial_broadcast) {
/* Call the function */
for (size_t i=0; i<size; ++i) {
output[i] = f((buffers[Index].size == 1
@ -364,8 +384,8 @@ struct vectorize_helper {
}
};
template <typename T> struct handle_type_name<array_t<T>> {
static PYBIND11_DESCR name() { return _("array[") + type_caster<T>::name() + _("]"); }
template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> {
static PYBIND11_DESCR name() { return _("numpy.ndarray[dtype=") + type_caster<T>::name() + _("]"); }
};
NAMESPACE_END(detail)

2
stormpy/resources/pybind11/include/pybind11/operators.h

@ -1,7 +1,7 @@
/*
pybind11/operator.h: Metatemplates for operator overloading
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

335
stormpy/resources/pybind11/include/pybind11/pybind11.h

@ -2,7 +2,7 @@
pybind11/pybind11.h: Main header file of the C++11 python
binding generator library
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -20,11 +20,13 @@
#elif defined(__ICC) || defined(__INTEL_COMPILER)
# pragma warning(push)
# pragma warning(disable:2196) // warning #2196: routine is both "inline" and "noinline"
#elif defined(__GNUG__) and !defined(__clang__)
#elif defined(__GNUG__) && !defined(__clang__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
# pragma GCC diagnostic ignored "-Wunused-but-set-variable"
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
# pragma GCC diagnostic ignored "-Wattributes"
#endif
#include "attr.h"
@ -33,77 +35,32 @@ NAMESPACE_BEGIN(pybind11)
/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
class cpp_function : public function {
protected:
/// Picks a suitable return value converter from cast.h
template <typename T> using return_value_caster =
detail::type_caster<typename std::conditional<
std::is_void<T>::value, detail::void_type, typename detail::intrinsic_type<T>::type>::type>;
/// Picks a suitable argument value converter from cast.h
template <typename... T> using arg_value_caster =
detail::type_caster<typename std::tuple<T...>>;
public:
cpp_function() { }
/// Vanilla function pointers
/// Construct a cpp_function from a vanilla function pointer
template <typename Return, typename... Args, typename... Extra>
cpp_function(Return (*f)(Args...), const Extra&... extra) {
auto rec = new detail::function_record();
rec->data = (void *) f;
typedef arg_value_caster<Args...> cast_in;
typedef return_value_caster<Return> cast_out;
/* Dispatch code which converts function arguments and performs the actual function call */
rec->impl = [](detail::function_record *rec, handle pyArgs, handle parent) -> handle {
cast_in args;
/* Try to cast the function arguments into the C++ domain */
if (!args.load(pyArgs, true))
return PYBIND11_TRY_NEXT_OVERLOAD;
/* Invoke call policy pre-call hook */
detail::process_attributes<Extra...>::precall(pyArgs);
/* Do the call and convert the return value back into the Python domain */
handle result = cast_out::cast(
args.template call<Return>((Return (*) (Args...)) rec->data),
rec->policy, parent);
/* Invoke call policy post-call hook */
detail::process_attributes<Extra...>::postcall(pyArgs, result);
return result;
};
/* Process any user-provided function attributes */
detail::process_attributes<Extra...>::init(extra..., rec);
/* Generate a readable signature describing the function's arguments and return value types */
using detail::descr;
PYBIND11_DESCR signature = cast_in::name() + detail::_(" -> ") + cast_out::name();
/* Register the function with Python from generic (non-templated) code */
initialize(rec, signature.text(), signature.types(), sizeof...(Args));
initialize(f, f, extra...);
}
/// Delegating helper constructor to deal with lambda functions
/// Construct a cpp_function from a lambda function (possibly with internal state)
template <typename Func, typename... Extra> cpp_function(Func &&f, const Extra&... extra) {
initialize(std::forward<Func>(f),
(typename detail::remove_class<decltype(
&std::remove_reference<Func>::type::operator())>::type *) nullptr, extra...);
}
/// Delegating helper constructor to deal with class methods (non-const)
template <typename Return, typename Class, typename... Arg, typename... Extra> cpp_function(
Return (Class::*f)(Arg...), const Extra&... extra) {
/// Construct a cpp_function from a class method (non-const)
template <typename Return, typename Class, typename... Arg, typename... Extra>
cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) {
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
(Return (*) (Class *, Arg...)) nullptr, extra...);
}
/// Delegating helper constructor to deal with class methods (const)
template <typename Return, typename Class, typename... Arg, typename... Extra> cpp_function(
Return (Class::*f)(Arg...) const, const Extra&... extra) {
/// Construct a cpp_function from a class method (const)
template <typename Return, typename Class, typename... Arg, typename... Extra>
cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) {
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
}
@ -119,35 +76,44 @@ protected:
/* Store the function including any extra state it might have (e.g. a lambda capture object) */
auto rec = new detail::function_record();
rec->data = new capture { std::forward<Func>(f) };
/* Create a cleanup handler, but only if we have to (less generated code) */
if (!std::is_trivially_destructible<Func>::value)
rec->free_data = [](void *ptr) { delete (capture *) ptr; };
else
rec->free_data = operator delete;
/* Store the capture object directly in the function record if there is enough space */
if (sizeof(capture) <= sizeof(rec->data)) {
new ((capture *) &rec->data) capture { std::forward<Func>(f) };
if (!std::is_trivially_destructible<Func>::value)
rec->free_data = [](detail::function_record *r) { ((capture *) &r->data)->~capture(); };
} else {
rec->data[0] = new capture { std::forward<Func>(f) };
rec->free_data = [](detail::function_record *r) { delete ((capture *) r->data[0]); };
}
typedef arg_value_caster<Args...> cast_in;
typedef return_value_caster<Return> cast_out;
/* Type casters for the function arguments and return value */
typedef detail::type_caster<typename std::tuple<Args...>> cast_in;
typedef detail::type_caster<typename std::conditional<
std::is_void<Return>::value, detail::void_type,
typename detail::intrinsic_type<Return>::type>::type> cast_out;
/* Dispatch code which converts function arguments and performs the actual function call */
rec->impl = [](detail::function_record *rec, handle pyArgs, handle parent) -> handle {
cast_in args;
rec->impl = [](detail::function_record *rec, handle args, handle kwargs, handle parent) -> handle {
cast_in args_converter;
/* Try to cast the function arguments into the C++ domain */
if (!args.load(pyArgs, true))
if (!args_converter.load_args(args, kwargs, true))
return PYBIND11_TRY_NEXT_OVERLOAD;
/* Invoke call policy pre-call hook */
detail::process_attributes<Extra...>::precall(pyArgs);
detail::process_attributes<Extra...>::precall(args);
/* Do the call and convert the return value back into the Python domain */
handle result = cast_out::cast(
args.template call<Return>(((capture *) rec->data)->f),
rec->policy, parent);
/* Get a pointer to the capture object */
capture *cap = (capture *) (sizeof(capture) <= sizeof(rec->data)
? &rec->data : rec->data[0]);
/* Perform the functioncall */
handle result = cast_out::cast(args_converter.template call<Return>(cap->f),
rec->policy, parent);
/* Invoke call policy post-call hook */
detail::process_attributes<Extra...>::postcall(pyArgs, result);
detail::process_attributes<Extra...>::postcall(args, result);
return result;
};
@ -160,12 +126,15 @@ protected:
PYBIND11_DESCR signature = cast_in::name() + detail::_(" -> ") + cast_out::name();
/* Register the function with Python from generic (non-templated) code */
initialize(rec, signature.text(), signature.types(), sizeof...(Args));
initialize_generic(rec, signature.text(), signature.types(), sizeof...(Args));
if (cast_in::has_args) rec->has_args = true;
if (cast_in::has_kwargs) rec->has_kwargs = true;
}
/// Register a function call with Python (generic non-templated code goes here)
void initialize(detail::function_record *rec, const char *text,
const std::type_info *const *types, int args) {
void initialize_generic(detail::function_record *rec, const char *text,
const std::type_info *const *types, int args) {
/* Create copies of all referenced C-style strings */
rec->name = strdup(rec->name ? rec->name : "");
@ -176,7 +145,7 @@ protected:
if (a.descr)
a.descr = strdup(a.descr);
else if (a.value)
a.descr = strdup(((std::string) ((object) handle(a.value).attr("__repr__")).call().str()).c_str());
a.descr = strdup(((std::string) ((object) handle(a.value).attr("__repr__"))().str()).c_str());
}
auto const &registered_types = detail::get_internals().registered_types_cpp;
@ -231,6 +200,9 @@ protected:
if (strcmp(rec->name, "__next__") == 0) {
std::free(rec->name);
rec->name = strdup("next");
} else if (strcmp(rec->name, "__bool__") == 0) {
std::free(rec->name);
rec->name = strdup("__nonzero__");
}
#endif
@ -240,9 +212,12 @@ protected:
std::to_string(args) + " arguments, but " + std::to_string(rec->args.size()) +
" pybind11::arg entries were specified!");
rec->is_constructor = !strcmp(rec->name, "__init__");
rec->signature = strdup(signature.c_str());
rec->args.shrink_to_fit();
rec->is_constructor = !strcmp(rec->name, "__init__") || !strcmp(rec->name, "__setstate__");
rec->has_args = false;
rec->has_kwargs = false;
rec->nargs = (uint16_t) args;
#if PY_MAJOR_VERSION < 3
if (rec->sibling && PyMethod_Check(rec->sibling.ptr()))
@ -336,7 +311,7 @@ protected:
while (rec) {
detail::function_record *next = rec->next;
if (rec->free_data)
rec->free_data(rec->data);
rec->free_data(rec);
std::free((char *) rec->name);
std::free((char *) rec->doc);
std::free((char *) rec->signature);
@ -361,15 +336,15 @@ protected:
*it = overloads;
/* Need to know how many arguments + keyword arguments there are to pick the right overload */
int nargs = (int) PyTuple_Size(args),
nkwargs = kwargs ? (int) PyDict_Size(kwargs) : 0;
size_t nargs = PyTuple_GET_SIZE(args),
nkwargs = kwargs ? PyDict_Size(kwargs) : 0;
handle parent = nargs > 0 ? PyTuple_GetItem(args, 0) : nullptr,
handle parent = nargs > 0 ? PyTuple_GET_ITEM(args, 0) : nullptr,
result = PYBIND11_TRY_NEXT_OVERLOAD;
try {
for (; it != nullptr; it = it->next) {
tuple args_(args, true);
int kwargs_consumed = 0;
size_t kwargs_consumed = 0;
/* For each overload:
1. If the required list of arguments is longer than the
@ -378,10 +353,11 @@ protected:
2. Ensure that all keyword arguments were "consumed"
3. Call the function call dispatcher (function_record::impl)
*/
if (nargs < (int) it->args.size()) {
args_ = tuple(it->args.size());
for (int i = 0; i < nargs; ++i) {
size_t nargs_ = nargs;
if (nargs < it->args.size()) {
nargs_ = it->args.size();
args_ = tuple(nargs_);
for (size_t i = 0; i < nargs; ++i) {
handle item = PyTuple_GET_ITEM(args, i);
PyTuple_SET_ITEM(args_.ptr(), i, item.inc_ref().ptr());
}
@ -404,20 +380,26 @@ protected:
if (value) {
PyTuple_SET_ITEM(args_.ptr(), index, value.inc_ref().ptr());
} else {
kwargs_consumed = -1; /* definite failure */
kwargs_consumed = (size_t) -1; /* definite failure */
break;
}
}
}
if (kwargs_consumed == nkwargs)
result = it->impl(it, args_, parent);
try {
if ((kwargs_consumed == nkwargs || it->has_kwargs) &&
(nargs_ == it->nargs || it->has_args))
result = it->impl(it, args_, kwargs, parent);
} catch (cast_error &) {
result = PYBIND11_TRY_NEXT_OVERLOAD;
}
if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD)
break;
}
} catch (const error_already_set &) { return nullptr;
} catch (const index_error &e) { PyErr_SetString(PyExc_IndexError, e.what()); return nullptr;
} catch (const value_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr;
} catch (const stop_iteration &e) { PyErr_SetString(PyExc_StopIteration, e.what()); return nullptr;
} catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return nullptr;
} catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr;
@ -440,6 +422,14 @@ protected:
msg += it2->signature;
msg += "\n";
}
msg += " Invoked with: ";
tuple args_(args, true);
for( std::size_t ti = 0; ti != args_.size(); ++ti)
{
msg += static_cast<std::string>(static_cast<object>(args_[ti]).str());
if ((ti + 1) != args_.size() )
msg += ", ";
}
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
} else if (!result) {
@ -450,9 +440,9 @@ protected:
return nullptr;
} else {
if (overloads->is_constructor) {
/* When a construtor ran successfully, the corresponding
/* When a constructor ran successfully, the corresponding
holder type (e.g. std::unique_ptr) must still be initialized. */
PyObject *inst = PyTuple_GetItem(args, 0);
PyObject *inst = PyTuple_GET_ITEM(args, 0);
auto tinfo = detail::get_type_info(Py_TYPE(inst));
tinfo->init_holder(inst, nullptr);
}
@ -937,10 +927,11 @@ public:
((it == entries->end()) ? std::string("???")
: std::string(it->second));
});
this->def("__init__", [](Type& value, int i) { value = (Type) i; });
this->def("__init__", [](Type& value, int i) { value = (Type)i; });
this->def("__init__", [](Type& value, int i) { new (&value) Type((Type) i); });
this->def("__int__", [](Type value) { return (int) value; });
this->def("__eq__", [](const Type &value, Type value2) { return value == value2; });
this->def("__ne__", [](const Type &value, Type value2) { return value != value2; });
this->def("__eq__", [](const Type &value, Type *value2) { return value2 && value == *value2; });
this->def("__ne__", [](const Type &value, Type *value2) { return !value2 || value != *value2; });
this->def("__hash__", [](const Type &value) { return (int) value; });
m_entries = entries;
}
@ -982,6 +973,9 @@ PYBIND11_NOINLINE inline void keep_alive_impl(int Nurse, int Patient, handle arg
if (!nurse || !patient)
pybind11_fail("Could not activate keep_alive!");
if (patient.ptr() == Py_None)
return; /* Nothing to keep alive */
cpp_function disable_lifesupport(
[patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); });
@ -1003,7 +997,7 @@ template <typename Iterator, typename... Extra> iterator make_iterator(Iterator
if (!detail::get_type_info(typeid(state))) {
class_<state>(handle(), "")
.def("__iter__", [](state &s) -> state& { return s; })
.def("__next__", [](state &s) -> decltype(*std::declval<Iterator>()) & {
.def("__next__", [](state &s) -> decltype(*std::declval<Iterator>()) {
if (s.it == s.end)
throw stop_iteration();
return *s.it++;
@ -1013,6 +1007,10 @@ template <typename Iterator, typename... Extra> iterator make_iterator(Iterator
return (iterator) cast(state { first, last });
}
template <typename Type, typename... Extra> iterator make_iterator(Type &value, Extra&&... extra) {
return make_iterator(std::begin(value), std::end(value), extra...);
}
template <typename InputType, typename OutputType> void implicitly_convertible() {
auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * {
if (!detail::type_caster<InputType>().load(obj, false))
@ -1032,21 +1030,126 @@ template <typename InputType, typename OutputType> void implicitly_convertible()
}
#if defined(WITH_THREAD)
inline void init_threading() { PyEval_InitThreads(); }
/* The functions below essentially reproduce the PyGILState_* API using a RAII
* pattern, but there are a few important differences:
*
* 1. When acquiring the GIL from an non-main thread during the finalization
* phase, the GILState API blindly terminates the calling thread, which
* is often not what is wanted. This API does not do this.
*
* 2. The gil_scoped_release function can optionally cut the relationship
* of a PyThreadState and its associated thread, which allows moving it to
* another thread (this is a fairly rare/advanced use case).
*
* 3. The reference count of an acquired thread state can be controlled. This
* can be handy to prevent cases where callbacks issued from an external
* thread would otherwise constantly construct and destroy thread state data
* structures.
*/
class gil_scoped_acquire {
PyGILState_STATE state;
public:
inline gil_scoped_acquire() { state = PyGILState_Ensure(); }
inline ~gil_scoped_acquire() { PyGILState_Release(state); }
PYBIND11_NOINLINE gil_scoped_acquire() {
auto const &internals = detail::get_internals();
tstate = (PyThreadState *) PyThread_get_key_value(internals.tstate);
if (!tstate) {
tstate = PyThreadState_New(internals.istate);
#if !defined(NDEBUG)
if (!tstate)
pybind11_fail("scoped_acquire: could not create thread state!");
#endif
tstate->gilstate_counter = 0;
#if PY_MAJOR_VERSION < 3
PyThread_delete_key_value(internals.tstate);
#endif
PyThread_set_key_value(internals.tstate, tstate);
} else {
release = detail::get_thread_state_unchecked() != tstate;
}
if (release) {
/* Work around an annoying assertion in PyThreadState_Swap */
#if defined(Py_DEBUG)
PyInterpreterState *interp = tstate->interp;
tstate->interp = nullptr;
#endif
PyEval_AcquireThread(tstate);
#if defined(Py_DEBUG)
tstate->interp = interp;
#endif
}
inc_ref();
}
void inc_ref() {
++tstate->gilstate_counter;
}
PYBIND11_NOINLINE void dec_ref() {
--tstate->gilstate_counter;
#if !defined(NDEBUG)
if (detail::get_thread_state_unchecked() != tstate)
pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!");
if (tstate->gilstate_counter < 0)
pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!");
#endif
if (tstate->gilstate_counter == 0) {
#if !defined(NDEBUG)
if (!release)
pybind11_fail("scoped_acquire::dec_ref(): internal error!");
#endif
PyThreadState_Clear(tstate);
PyThreadState_DeleteCurrent();
PyThread_delete_key_value(detail::get_internals().tstate);
release = false;
}
}
PYBIND11_NOINLINE ~gil_scoped_acquire() {
dec_ref();
if (release)
PyEval_SaveThread();
}
private:
PyThreadState *tstate = nullptr;
bool release = true;
};
class gil_scoped_release {
PyThreadState *state;
public:
inline gil_scoped_release() { state = PyEval_SaveThread(); }
inline ~gil_scoped_release() { PyEval_RestoreThread(state); }
gil_scoped_release(bool disassoc = false) : disassoc(disassoc) {
tstate = PyEval_SaveThread();
if (disassoc) {
int key = detail::get_internals().tstate;
#if PY_MAJOR_VERSION < 3
PyThread_delete_key_value(key);
#else
PyThread_set_key_value(key, nullptr);
#endif
}
}
~gil_scoped_release() {
if (!tstate)
return;
PyEval_RestoreThread(tstate);
if (disassoc) {
int key = detail::get_internals().tstate;
#if PY_MAJOR_VERSION < 3
PyThread_delete_key_value(key);
#endif
PyThread_set_key_value(key, tstate);
}
}
private:
PyThreadState *tstate;
bool disassoc;
};
#else
class gil_scoped_acquire { };
class gil_scoped_release { };
#endif
inline function get_overload(const void *this_ptr, const char *name) {
@ -1081,19 +1184,25 @@ inline function get_overload(const void *this_ptr, const char *name) {
return overload;
}
#define PYBIND11_OVERLOAD_INT(ret_type, class_name, name, ...) { \
#define PYBIND11_OVERLOAD_INT(ret_type, name, ...) { \
pybind11::gil_scoped_acquire gil; \
pybind11::function overload = pybind11::get_overload(this, #name); \
pybind11::function overload = pybind11::get_overload(this, name); \
if (overload) \
return overload.call(__VA_ARGS__).template cast<ret_type>(); }
return overload(__VA_ARGS__).template cast<ret_type>(); }
#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERLOAD_INT(ret_type, name, __VA_ARGS__) \
return cname::fn(__VA_ARGS__)
#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERLOAD_INT(ret_type, name, __VA_ARGS__) \
pybind11::pybind11_fail("Tried to call pure virtual function \"" #cname "::" name "\"");
#define PYBIND11_OVERLOAD(ret_type, class_name, name, ...) \
PYBIND11_OVERLOAD_INT(ret_type, class_name, name, __VA_ARGS__) \
return class_name::name(__VA_ARGS__)
#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \
PYBIND11_OVERLOAD_NAME(ret_type, cname, #fn, fn, __VA_ARGS__)
#define PYBIND11_OVERLOAD_PURE(ret_type, class_name, name, ...) \
PYBIND11_OVERLOAD_INT(ret_type, class_name, name, __VA_ARGS__) \
pybind11::pybind11_fail("Tried to call pure virtual function \"" #name "\"");
#define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \
PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, #fn, fn, __VA_ARGS__)
NAMESPACE_END(pybind11)
@ -1101,6 +1210,6 @@ NAMESPACE_END(pybind11)
# pragma warning(pop)
#elif defined(__ICC) || defined(__INTEL_COMPILER)
# pragma warning(pop)
#elif defined(__GNUG__) and !defined(__clang__)
#elif defined(__GNUG__) && !defined(__clang__)
# pragma GCC diagnostic pop
#endif

174
stormpy/resources/pybind11/include/pybind11/pytypes.h

@ -1,7 +1,7 @@
/*
pybind11/typeid.h: Convenience wrapper classes for basic Python types
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
@ -16,12 +16,8 @@
NAMESPACE_BEGIN(pybind11)
/* A few forward declarations */
class object;
class str;
class object;
class dict;
class iterator;
namespace detail { class accessor; }
class object; class str; class object; class dict; class iterator;
namespace detail { class accessor; class args_proxy; class kwargs_proxy; }
/// Holds a reference to a Python object (no reference counting)
class handle {
@ -43,11 +39,17 @@ public:
inline detail::accessor attr(const char *key) const;
inline pybind11::str str() const;
template <typename T> T cast() const;
template <typename ... Args> object call(Args&&... args_) const;
template <typename ... Args>
[[deprecated("call(...) was deprecated in favor of operator()(...)")]]
object call(Args&&... args) const;
template <typename ... Args> object operator()(Args&&... args) const;
inline object operator()(detail::args_proxy args) const;
inline object operator()(detail::args_proxy f_args, detail::kwargs_proxy kwargs) const;
operator bool() const { return m_ptr != nullptr; }
bool operator==(const handle &h) const { return m_ptr == h.m_ptr; }
bool operator!=(const handle &h) const { return m_ptr != h.m_ptr; }
bool check() const { return m_ptr != nullptr; }
inline detail::args_proxy operator*() const;
protected:
PyObject *m_ptr;
};
@ -59,7 +61,7 @@ public:
object(const object &o) : handle(o) { inc_ref(); }
object(const handle &h, bool borrowed) : handle(h) { if (borrowed) inc_ref(); }
object(PyObject *ptr, bool borrowed) : handle(ptr) { if (borrowed) inc_ref(); }
object(object &&other) { m_ptr = other.m_ptr; other.m_ptr = nullptr; }
object(object &&other) noexcept { m_ptr = other.m_ptr; other.m_ptr = nullptr; }
~object() { dec_ref(); }
handle release() {
@ -68,14 +70,14 @@ public:
return handle(tmp);
}
object& operator=(object &other) {
object& operator=(const object &other) {
other.inc_ref();
dec_ref();
m_ptr = other.m_ptr;
return *this;
}
object& operator=(object &&other) {
object& operator=(object &&other) noexcept {
if (this != &other) {
handle temp(m_ptr);
m_ptr = other.m_ptr;
@ -126,7 +128,7 @@ public:
return result;
}
template <typename T> inline T cast() const { return operator object().cast<T>(); }
template <typename T> T cast() const { return operator object().cast<T>(); }
operator bool() const {
if (attr) {
@ -163,7 +165,7 @@ public:
return object(result, true);
}
template <typename T> inline T cast() const { return operator object().cast<T>(); }
template <typename T> T cast() const { return operator object().cast<T>(); }
private:
handle list;
size_t index;
@ -188,7 +190,7 @@ public:
return object(result, true);
}
template <typename T> inline T cast() const { return operator object().cast<T>(); }
template <typename T> T cast() const { return operator object().cast<T>(); }
private:
handle tuple;
size_t index;
@ -212,16 +214,42 @@ private:
ssize_t pos = 0;
};
NAMESPACE_END(detail)
inline bool PyIterable_Check(PyObject *obj) {
PyObject *iter = PyObject_GetIter(obj);
if (iter) {
Py_DECREF(iter);
return true;
} else {
PyErr_Clear();
return false;
}
}
inline bool PyNone_Check(PyObject *o) { return o == Py_None; }
inline bool PyUnicode_Check_Permissive(PyObject *o) { return PyUnicode_Check(o) || PYBIND11_BYTES_CHECK(o); }
class kwargs_proxy : public handle {
public:
kwargs_proxy(handle h) : handle(h) { }
};
class args_proxy : public handle {
public:
args_proxy(handle h) : handle(h) { }
kwargs_proxy operator*() const { return kwargs_proxy(*this); }
};
NAMESPACE_END(detail)
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, CvtStmt) \
Name(const handle &h, bool borrowed) : Parent(h, borrowed) { CvtStmt; } \
Name(const object& o): Parent(o) { CvtStmt; } \
Name(object&& o): Parent(std::move(o)) { CvtStmt; } \
Name& operator=(object&& o) { (void) static_cast<Name&>(object::operator=(std::move(o))); CvtStmt; return *this; } \
Name& operator=(object& o) { return static_cast<Name&>(object::operator=(o)); CvtStmt; } \
bool check() const { return m_ptr != nullptr && (bool) CheckFun(m_ptr); }
public: \
Name(const handle &h, bool borrowed) : Parent(h, borrowed) { CvtStmt; } \
Name(const object& o): Parent(o) { CvtStmt; } \
Name(object&& o) noexcept : Parent(std::move(o)) { CvtStmt; } \
Name& operator=(object&& o) noexcept { (void) object::operator=(std::move(o)); CvtStmt; return *this; } \
Name& operator=(const object& o) { return static_cast<Name&>(object::operator=(o)); CvtStmt; } \
bool check() const { return m_ptr != nullptr && (bool) CheckFun(m_ptr); }
#define PYBIND11_OBJECT(Name, Parent, CheckFun) \
PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, )
@ -232,48 +260,99 @@ NAMESPACE_END(detail)
class iterator : public object {
public:
PYBIND11_OBJECT_DEFAULT(iterator, object, PyIter_Check)
iterator(handle obj, bool borrowed = false) : object(obj, borrowed) { }
PYBIND11_OBJECT_CVT(iterator, object, PyIter_Check, value = object(); ready = false)
iterator() : object(), value(object()), ready(false) { }
iterator(const iterator& it) : object(it), value(it.value), ready(it.ready) { }
iterator(iterator&& it) : object(std::move(it)), value(std::move(it.value)), ready(it.ready) { }
/** Caveat: this copy constructor does not (and cannot) clone the internal
state of the Python iterable */
iterator &operator=(const iterator &it) {
(void) object::operator=(it);
value = it.value;
ready = it.ready;
return *this;
}
iterator &operator=(iterator &&it) noexcept {
(void) object::operator=(std::move(it));
value = std::move(it.value);
ready = it.ready;
return *this;
}
iterator& operator++() {
if (ptr())
value = object(PyIter_Next(m_ptr), false);
if (m_ptr)
advance();
return *this;
}
/** Caveat: this postincrement operator does not (and cannot) clone the
internal state of the Python iterable. It should only be used to
retrieve the current iterate using <tt>operator*()</tt> */
iterator operator++(int) {
iterator rv(*this);
rv.value = value;
if (m_ptr)
advance();
return rv;
}
bool operator==(const iterator &it) const { return *it == **this; }
bool operator!=(const iterator &it) const { return *it != **this; }
const handle &operator*() const {
if (m_ptr && !value)
value = object(PyIter_Next(m_ptr), false);
handle operator*() const {
if (!ready && m_ptr) {
auto& self = const_cast<iterator &>(*this);
self.advance();
self.ready = true;
}
return value;
}
private:
void advance() { value = object(PyIter_Next(m_ptr), false); }
private:
mutable object value;
object value;
bool ready;
};
class iterable : public object {
public:
PYBIND11_OBJECT_DEFAULT(iterable, object, detail::PyIterable_Check)
};
inline detail::accessor handle::operator[](handle key) const { return detail::accessor(ptr(), key.ptr(), false); }
inline detail::accessor handle::operator[](const char *key) const { return detail::accessor(ptr(), key, false); }
inline detail::accessor handle::attr(handle key) const { return detail::accessor(ptr(), key.ptr(), true); }
inline detail::accessor handle::attr(const char *key) const { return detail::accessor(ptr(), key, true); }
inline iterator handle::begin() const { return iterator(PyObject_GetIter(ptr())); }
inline iterator handle::end() const { return iterator(nullptr); }
inline iterator handle::begin() const { return iterator(PyObject_GetIter(ptr()), false); }
inline iterator handle::end() const { return iterator(nullptr, false); }
inline detail::args_proxy handle::operator*() const { return detail::args_proxy(*this); }
class str : public object {
public:
PYBIND11_OBJECT_DEFAULT(str, object, PyUnicode_Check)
PYBIND11_OBJECT_DEFAULT(str, object, detail::PyUnicode_Check_Permissive)
str(const std::string &s)
: object(PyUnicode_FromStringAndSize(s.c_str(), s.length()), false) {
if (!m_ptr) pybind11_fail("Could not allocate string object!");
}
operator std::string() const {
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
return PyUnicode_AsUTF8(m_ptr);
#else
object temp(PyUnicode_AsUTF8String(m_ptr), false);
if (temp.ptr() == nullptr)
pybind11_fail("Unable to extract string contents!");
return PYBIND11_BYTES_AS_STRING(temp.ptr());
#endif
object temp = *this;
if (PyUnicode_Check(m_ptr)) {
temp = object(PyUnicode_AsUTF8String(m_ptr), false);
if (!temp)
pybind11_fail("Unable to extract string contents! (encoding issue)");
}
char *buffer;
ssize_t length;
int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length);
if (err == -1)
pybind11_fail("Unable to extract string contents! (invalid type)");
return std::string(buffer, length);
}
};
@ -305,6 +384,12 @@ public:
}
};
class none : public object {
public:
PYBIND11_OBJECT(none, object, detail::PyNone_Check)
none() : object(Py_None, true) { }
};
class bool_ : public object {
public:
PYBIND11_OBJECT_DEFAULT(bool_, object, PyBool_Check)
@ -388,8 +473,8 @@ class capsule : public object {
public:
PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact)
capsule(PyObject *obj, bool borrowed) : object(obj, borrowed) { }
capsule(void *value, void (*destruct)(PyObject *) = nullptr)
: object(PyCapsule_New(value, nullptr, destruct), false) {
capsule(const void *value, void (*destruct)(PyObject *) = nullptr)
: object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), false) {
if (!m_ptr) pybind11_fail("Could not allocate capsule object!");
}
template <typename T> operator T *() const {
@ -406,7 +491,7 @@ public:
if (!m_ptr) pybind11_fail("Could not allocate tuple object!");
}
size_t size() const { return (size_t) PyTuple_Size(m_ptr); }
detail::tuple_accessor operator[](size_t index) const { return detail::tuple_accessor(ptr(), index); }
detail::tuple_accessor operator[](size_t index) const { return detail::tuple_accessor(*this, index); }
};
class dict : public object {
@ -432,6 +517,9 @@ public:
void append(const object &object) const { PyList_Append(m_ptr, object.ptr()); }
};
class args : public tuple { PYBIND11_OBJECT_DEFAULT(args, tuple, PyTuple_Check) };
class kwargs : public dict { PYBIND11_OBJECT_DEFAULT(kwargs, dict, PyDict_Check) };
class set : public object {
public:
PYBIND11_OBJECT(set, object, PySet_Check)

4
stormpy/resources/pybind11/include/pybind11/stl.h

@ -1,7 +1,7 @@
/*
pybind11/complex.h: Complex number support
pybind11/stl.h: Transparent conversion for STL data types
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

349
stormpy/resources/pybind11/include/pybind11/stl_bind.h

@ -0,0 +1,349 @@
/*
pybind11/std_bind.h: Binding generators for STL data types
Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#pragma once
#include "common.h"
#include "operators.h"
#include <type_traits>
#include <utility>
#include <algorithm>
#include <sstream>
NAMESPACE_BEGIN(pybind11)
NAMESPACE_BEGIN(detail)
/* SFINAE helper class used by 'is_comparable */
template <typename T> struct container_traits {
template <typename T2> static std::true_type test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>())*);
template <typename T2> static std::false_type test_comparable(...);
template <typename T2> static std::true_type test_value(typename T2::value_type *);
template <typename T2> static std::false_type test_value(...);
template <typename T2> static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *);
template <typename T2> static std::false_type test_pair(...);
static constexpr const bool is_comparable = std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value;
static constexpr const bool is_pair = std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value;
static constexpr const bool is_vector = std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value;
static constexpr const bool is_element = !is_pair && !is_vector;
};
/* Default: is_comparable -> std::false_type */
template <typename T, typename SFINAE = void>
struct is_comparable : std::false_type { };
/* For non-map data structures, check whether operator== can be instantiated */
template <typename T>
struct is_comparable<
T, typename std::enable_if<container_traits<T>::is_element &&
container_traits<T>::is_comparable>::type>
: std::true_type { };
/* For a vector/map data structure, recursively check the value type (which is std::pair for maps) */
template <typename T>
struct is_comparable<T, typename std::enable_if<container_traits<T>::is_vector>::type> {
static constexpr const bool value =
is_comparable<typename T::value_type>::value;
};
/* For pairs, recursively check the two data types */
template <typename T>
struct is_comparable<T, typename std::enable_if<container_traits<T>::is_pair>::type> {
static constexpr const bool value =
is_comparable<typename T::first_type>::value &&
is_comparable<typename T::second_type>::value;
};
/* Fallback functions */
template <typename, typename, typename... Args> void vector_if_copy_constructible(const Args&...) { }
template <typename, typename, typename... Args> void vector_if_equal_operator(const Args&...) { }
template <typename, typename, typename... Args> void vector_if_insertion_operator(const Args&...) { }
template<typename Vector, typename Class_, typename std::enable_if<std::is_copy_constructible<typename Vector::value_type>::value, int>::type = 0>
void vector_if_copy_constructible(Class_ &cl) {
cl.def(pybind11::init<const Vector &>(),
"Copy constructor");
}
template<typename Vector, typename Class_, typename std::enable_if<is_comparable<Vector>::value, int>::type = 0>
void vector_if_equal_operator(Class_ &cl) {
using T = typename Vector::value_type;
cl.def(self == self);
cl.def(self != self);
cl.def("count",
[](const Vector &v, const T &x) {
return std::count(v.begin(), v.end(), x);
},
arg("x"),
"Return the number of times ``x`` appears in the list"
);
cl.def("remove", [](Vector &v, const T &x) {
auto p = std::find(v.begin(), v.end(), x);
if (p != v.end())
v.erase(p);
else
throw pybind11::value_error();
},
arg("x"),
"Remove the first item from the list whose value is x. "
"It is an error if there is no such item."
);
cl.def("__contains__",
[](const Vector &v, const T &x) {
return std::find(v.begin(), v.end(), x) != v.end();
},
arg("x"),
"Return true the container contains ``x``"
);
}
template <typename Vector, typename Class_> auto vector_if_insertion_operator(Class_ &cl, std::string const &name)
-> decltype(std::declval<std::ostream&>() << std::declval<typename Vector::value_type>(), void()) {
using size_type = typename Vector::size_type;
cl.def("__repr__",
[name](Vector &v) {
std::ostringstream s;
s << name << '[';
for (size_type i=0; i < v.size(); ++i) {
s << v[i];
if (i != v.size() - 1)
s << ", ";
}
s << ']';
return s.str();
},
"Return the canonical string representation of this list."
);
}
NAMESPACE_END(detail)
template <typename T, typename Allocator = std::allocator<T>, typename holder_type = std::unique_ptr<std::vector<T, Allocator>>, typename... Args>
pybind11::class_<std::vector<T, Allocator>, holder_type> bind_vector(pybind11::module &m, std::string const &name, Args&&... args) {
using Vector = std::vector<T, Allocator>;
using SizeType = typename Vector::size_type;
using Class_ = pybind11::class_<Vector, holder_type>;
Class_ cl(m, name.c_str(), std::forward<Args>(args)...);
cl.def(pybind11::init<>());
// Register copy constructor (if possible)
detail::vector_if_copy_constructible<Vector, Class_>(cl);
// Register comparison-related operators and functions (if possible)
detail::vector_if_equal_operator<Vector, Class_>(cl);
// Register stream insertion operator (if possible)
detail::vector_if_insertion_operator<Vector, Class_>(cl, name);
cl.def("__init__", [](Vector &v, iterable it) {
new (&v) Vector();
try {
v.reserve(len(it));
for (handle h : it)
v.push_back(h.cast<typename Vector::value_type>());
} catch (...) {
v.~Vector();
throw;
}
});
cl.def("append", (void (Vector::*) (const T &)) & Vector::push_back,
arg("x"),
"Add an item to the end of the list");
cl.def("extend",
[](Vector &v, Vector &src) {
v.reserve(v.size() + src.size());
v.insert(v.end(), src.begin(), src.end());
},
arg("L"),
"Extend the list by appending all the items in the given list"
);
cl.def("insert",
[](Vector &v, SizeType i, const T &x) {
v.insert(v.begin() + i, x);
},
arg("i") , arg("x"),
"Insert an item at a given position."
);
cl.def("pop",
[](Vector &v) {
if (v.empty())
throw pybind11::index_error();
T t = v.back();
v.pop_back();
return t;
},
"Remove and return the last item"
);
cl.def("pop",
[](Vector &v, SizeType i) {
if (i >= v.size())
throw pybind11::index_error();
T t = v[i];
v.erase(v.begin() + i);
return t;
},
arg("i"),
"Remove and return the item at index ``i``"
);
cl.def("__bool__",
[](const Vector &v) -> bool {
return !v.empty();
},
"Check whether the list is nonempty"
);
cl.def("__getitem__",
[](const Vector &v, SizeType i) {
if (i >= v.size())
throw pybind11::index_error();
return v[i];
}
);
cl.def("__setitem__",
[](Vector &v, SizeType i, const T &t) {
if (i >= v.size())
throw pybind11::index_error();
v[i] = t;
}
);
cl.def("__delitem__",
[](Vector &v, SizeType i) {
if (i >= v.size())
throw pybind11::index_error();
v.erase(v.begin() + i);
},
"Delete list elements using a slice object"
);
cl.def("__len__", &Vector::size);
cl.def("__iter__",
[](Vector &v) {
return pybind11::make_iterator(v.begin(), v.end());
},
pybind11::keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
);
/// Slicing protocol
cl.def("__getitem__",
[](const Vector &v, slice slice) -> Vector * {
ssize_t start, stop, step, slicelength;
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
throw pybind11::error_already_set();
Vector *seq = new Vector();
seq->reserve((size_t) slicelength);
for (int i=0; i<slicelength; ++i) {
seq->push_back(v[start]);
start += step;
}
return seq;
},
arg("s"),
"Retrieve list elements using a slice object"
);
cl.def("__setitem__",
[](Vector &v, slice slice, const Vector &value) {
ssize_t start, stop, step, slicelength;
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
throw pybind11::error_already_set();
if ((size_t) slicelength != value.size())
throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
for (int i=0; i<slicelength; ++i) {
v[start] = value[i];
start += step;
}
},
"Assign list elements using a slice object"
);
cl.def("__delitem__",
[](Vector &v, slice slice) {
ssize_t start, stop, step, slicelength;
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
throw pybind11::error_already_set();
if (step == 1 && false) {
v.erase(v.begin() + start, v.begin() + start + slicelength);
} else {
for (ssize_t i = 0; i < slicelength; ++i) {
v.erase(v.begin() + start);
start += step - 1;
}
}
},
"Delete list elements using a slice object"
);
#if 0
// C++ style functions deprecated, leaving it here as an example
cl.def(pybind11::init<size_type>());
cl.def("resize",
(void (Vector::*) (size_type count)) & Vector::resize,
"changes the number of elements stored");
cl.def("erase",
[](Vector &v, SizeType i) {
if (i >= v.size())
throw pybind11::index_error();
v.erase(v.begin() + i);
}, "erases element at index ``i``");
cl.def("empty", &Vector::empty, "checks whether the container is empty");
cl.def("size", &Vector::size, "returns the number of elements");
cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end");
cl.def("pop_back", &Vector::pop_back, "removes the last element");
cl.def("max_size", &Vector::max_size, "returns the maximum possible number of elements");
cl.def("reserve", &Vector::reserve, "reserves storage");
cl.def("capacity", &Vector::capacity, "returns the number of elements that can be held in currently allocated storage");
cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory");
cl.def("clear", &Vector::clear, "clears the contents");
cl.def("swap", &Vector::swap, "swaps the contents");
cl.def("front", [](Vector &v) {
if (v.size()) return v.front();
else throw pybind11::index_error();
}, "access the first element");
cl.def("back", [](Vector &v) {
if (v.size()) return v.back();
else throw pybind11::index_error();
}, "access the last element ");
#endif
return cl;
}
NAMESPACE_END(pybind11)

2
stormpy/resources/pybind11/include/pybind11/typeid.h

@ -1,7 +1,7 @@
/*
pybind11/typeid.h: Compiler-independent access to type identifiers
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.

4
stormpy/resources/pybind11/pybind11/__init__.py

@ -1,11 +1,11 @@
from ._version import version_info, __version__
def get_include():
def get_include(*args, **kwargs):
import os
try:
from pip import locations
return os.path.dirname(
locations.distutils_scheme('pybind11')['headers'])
locations.distutils_scheme('pybind11', *args, **kwargs)['headers'])
except ImportError:
return 'include'

2
stormpy/resources/pybind11/pybind11/_version.py

@ -1,2 +1,2 @@
version_info = (1, 5, 'dev0')
version_info = (1, 8, 'dev0')
__version__ = '.'.join(map(str, version_info))

4
stormpy/resources/pybind11/setup.py

@ -10,7 +10,7 @@ setup(
version=__version__,
description='Seamless operability between C++11 and Python',
author='Wenzel Jakob',
author_email='wenzel@inf.ethz.ch',
author_email='wenzel.jakob@epfl.ch',
url='https://github.com/wjakob/pybind11',
download_url='https://github.com/wjakob/pybind11/tarball/v' + __version__,
packages=['pybind11'],
@ -20,9 +20,11 @@ setup(
'include/pybind11/cast.h',
'include/pybind11/complex.h',
'include/pybind11/descr.h',
'include/pybind11/eigen.h',
'include/pybind11/numpy.h',
'include/pybind11/pybind11.h',
'include/pybind11/stl.h',
'include/pybind11/stl_bind.h',
'include/pybind11/common.h',
'include/pybind11/functional.h',
'include/pybind11/operators.h',

81
stormpy/resources/pybind11/tools/FindEigen3.cmake

@ -0,0 +1,81 @@
# - Try to find Eigen3 lib
#
# This module supports requiring a minimum version, e.g. you can do
# find_package(Eigen3 3.1.2)
# to require version 3.1.2 or newer of Eigen3.
#
# Once done this will define
#
# EIGEN3_FOUND - system has eigen lib with correct version
# EIGEN3_INCLUDE_DIR - the eigen include directory
# EIGEN3_VERSION - eigen version
# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
# Copyright (c) 2008, 2009 Gael Guennebaud, <g.gael@free.fr>
# Copyright (c) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
# Redistribution and use is allowed according to the terms of the 2-clause BSD license.
if(NOT Eigen3_FIND_VERSION)
if(NOT Eigen3_FIND_VERSION_MAJOR)
set(Eigen3_FIND_VERSION_MAJOR 2)
endif(NOT Eigen3_FIND_VERSION_MAJOR)
if(NOT Eigen3_FIND_VERSION_MINOR)
set(Eigen3_FIND_VERSION_MINOR 91)
endif(NOT Eigen3_FIND_VERSION_MINOR)
if(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION_PATCH 0)
endif(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}")
endif(NOT Eigen3_FIND_VERSION)
macro(_eigen3_check_version)
file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}")
set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}")
set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}")
set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION})
if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK FALSE)
else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK TRUE)
endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
if(NOT EIGEN3_VERSION_OK)
message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, "
"but at least version ${Eigen3_FIND_VERSION} is required")
endif(NOT EIGEN3_VERSION_OK)
endmacro(_eigen3_check_version)
if (EIGEN3_INCLUDE_DIR)
# in cache already
_eigen3_check_version()
set(EIGEN3_FOUND ${EIGEN3_VERSION_OK})
else (EIGEN3_INCLUDE_DIR)
find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
PATHS
${CMAKE_INSTALL_PREFIX}/include
${KDE4_INCLUDE_DIR}
PATH_SUFFIXES eigen3 eigen
)
if(EIGEN3_INCLUDE_DIR)
_eigen3_check_version()
endif(EIGEN3_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
mark_as_advanced(EIGEN3_INCLUDE_DIR)
endif(EIGEN3_INCLUDE_DIR)

200
stormpy/resources/pybind11/tools/mkdoc.py

@ -5,64 +5,72 @@
# Extract documentation from C++ header files to use it in Python bindings
#
import os, sys, platform, re, textwrap
import os
import sys
import platform
import re
import textwrap
from clang import cindex
from clang.cindex import CursorKind
from collections import OrderedDict
from threading import Thread, Semaphore
from multiprocessing import cpu_count
if platform.system() == 'Darwin':
libclang = '/opt/llvm/lib/libclang.dylib'
if os.path.exists(libclang):
cindex.Config.set_library_path(os.path.dirname(libclang))
RECURSE_LIST = [
CursorKind.TRANSLATION_UNIT,
CursorKind.NAMESPACE,
CursorKind.CLASS_DECL,
CursorKind.STRUCT_DECL,
CursorKind.ENUM_DECL,
CursorKind.CLASS_TEMPLATE
]
PRINT_LIST = [
CursorKind.CLASS_DECL,
CursorKind.STRUCT_DECL,
CursorKind.ENUM_DECL,
CursorKind.ENUM_CONSTANT_DECL,
CursorKind.CLASS_TEMPLATE,
CursorKind.FUNCTION_DECL,
CursorKind.FUNCTION_TEMPLATE,
CursorKind.CONVERSION_FUNCTION,
CursorKind.CXX_METHOD,
CursorKind.CONSTRUCTOR,
CursorKind.FIELD_DECL
]
CPP_OPERATORS = {
'<=' : 'le', '>=' : 'ge', '==' : 'eq', '!=' : 'ne', '[]' : 'array',
'+=' : 'iadd', '-=' : 'isub', '*=' : 'imul', '/=' : 'idiv', '%=' :
'imod', '&=' : 'iand', '|=' : 'ior', '^=' : 'ixor', '<<=' : 'ilshift',
'>>=' : 'irshift', '++' : 'inc', '--' : 'dec', '<<' : 'lshift', '>>' :
'rshift', '&&' : 'land', '||' : 'lor', '!' : 'lnot', '~' : 'bnot', '&'
: 'band', '|' : 'bor', '+' : 'add', '-' : 'sub', '*' : 'mul', '/' :
'div', '%' : 'mod', '<' : 'lt', '>' : 'gt', '=' : 'assign'
'<=': 'le', '>=': 'ge', '==': 'eq', '!=': 'ne', '[]': 'array',
'+=': 'iadd', '-=': 'isub', '*=': 'imul', '/=': 'idiv', '%=':
'imod', '&=': 'iand', '|=': 'ior', '^=': 'ixor', '<<=': 'ilshift',
'>>=': 'irshift', '++': 'inc', '--': 'dec', '<<': 'lshift', '>>':
'rshift', '&&': 'land', '||': 'lor', '!': 'lnot', '~': 'bnot',
'&': 'band', '|': 'bor', '+': 'add', '-': 'sub', '*': 'mul', '/':
'div', '%': 'mod', '<': 'lt', '>': 'gt', '=': 'assign', '()': 'call'
}
CPP_OPERATORS = OrderedDict(sorted(CPP_OPERATORS.items(), key=lambda t: -len(t[0])))
CPP_OPERATORS = OrderedDict(
sorted(CPP_OPERATORS.items(), key=lambda t: -len(t[0])))
job_count = cpu_count()
job_semaphore = Semaphore(job_count)
registered_names = dict()
def d(s):
return s.decode('utf8')
def sanitize_name(name):
global registered_names
name = re.sub(r'type-parameter-0-([0-9]+)', r'T\1', name)
for k, v in CPP_OPERATORS.items():
name = name.replace('operator%s' % k, 'operator_%s' % v)
name = name.replace('<', '_')
name = name.replace('>', '_')
name = name.replace(' ', '_')
name = name.replace(',', '_')
name = re.sub('<.*>', '', name)
name = ''.join([ch if ch.isalnum() else '_' for ch in name])
name = re.sub('_$', '', re.sub('_+', '_', name))
if name in registered_names:
registered_names[name] += 1
name += '_' + str(registered_names[name])
@ -70,21 +78,31 @@ def sanitize_name(name):
registered_names[name] = 1
return '__doc_' + name
def process_comment(comment):
result = ''
# Remove C++ comment syntax
for s in comment.splitlines():
leading_spaces = float('inf')
for s in comment.expandtabs(tabsize=4).splitlines():
s = s.strip()
if s.startswith('/*'):
s = s[2:].lstrip('* \t')
s = s[2:].lstrip('*')
elif s.endswith('*/'):
s = s[:-2].rstrip('* \t')
s = s[:-2].rstrip('*')
elif s.startswith('///'):
s = s[3:]
if s.startswith('*'):
s = s[1:]
result += s.strip() + '\n'
if len(s) > 0:
leading_spaces = min(leading_spaces, len(s) - len(s.lstrip()))
result += s + '\n'
if leading_spaces != float('inf'):
result2 = ""
for s in result.splitlines():
result2 += s[leading_spaces:] + '\n'
result = result2
# Doxygen tags
cpp_group = '([\w:]+)'
@ -96,20 +114,25 @@ def process_comment(comment):
s = re.sub(r'\\e\s+%s' % cpp_group, r'*\1*', s)
s = re.sub(r'\\em\s+%s' % cpp_group, r'*\1*', s)
s = re.sub(r'\\b\s+%s' % cpp_group, r'**\1**', s)
s = re.sub(r'\\param%s?\s+%s' % (param_group, cpp_group), r'\n\n$Parameter ``\2``:\n\n', s)
s = re.sub(r'\\ingroup\s+%s' % cpp_group, r'', s)
s = re.sub(r'\\param%s?\s+%s' % (param_group, cpp_group),
r'\n\n$Parameter ``\2``:\n\n', s)
s = re.sub(r'\\tparam%s?\s+%s' % (param_group, cpp_group),
r'\n\n$Template parameter ``\2``:\n\n', s)
for in_, out_ in {
'return' : 'Returns',
'author' : 'Author',
'authors' : 'Authors',
'copyright' : 'Copyright',
'date' : 'Date',
'remark' : 'Remark',
'sa' : 'See also',
'see' : 'See also',
'extends' : 'Extends',
'throw' : 'Throws',
'throws' : 'Throws' }.items():
'return': 'Returns',
'author': 'Author',
'authors': 'Authors',
'copyright': 'Copyright',
'date': 'Date',
'remark': 'Remark',
'sa': 'See also',
'see': 'See also',
'extends': 'Extends',
'throw': 'Throws',
'throws': 'Throws'
}.items():
s = re.sub(r'\\%s\s*' % in_, r'\n\n$%s:\n\n' % out_, s)
s = re.sub(r'\\details\s*', r'\n\n', s)
@ -117,11 +140,18 @@ def process_comment(comment):
s = re.sub(r'\\short\s*', r'', s)
s = re.sub(r'\\ref\s*', r'', s)
s = re.sub(r'\\code\s?(.*?)\s?\\endcode',
r"```\n\1\n```\n", s, flags=re.DOTALL)
# HTML/TeX tags
s = re.sub(r'<tt>([^<]*)</tt>', r'``\1``', s)
s = re.sub(r'<em>([^<]*)</em>', r'*\1*', s)
s = re.sub(r'<b>([^<]*)</b>', r'**\1**', s)
s = re.sub(r'\\f\$([^\$]*)\\f\$', r'$\1$', s)
s = re.sub(r'<tt>(.*?)</tt>', r'``\1``', s, flags=re.DOTALL)
s = re.sub(r'<pre>(.*?)</pre>', r"```\n\1\n```\n", s, flags=re.DOTALL)
s = re.sub(r'<em>(.*?)</em>', r'*\1*', s, flags=re.DOTALL)
s = re.sub(r'<b>(.*?)</b>', r'**\1**', s, flags=re.DOTALL)
s = re.sub(r'\\f\$(.*?)\\f\$', r'$\1$', s, flags=re.DOTALL)
s = re.sub(r'<li>', r'\n\n* ', s)
s = re.sub(r'</?ul>', r'', s)
s = re.sub(r'</li>', r'\n\n', s)
s = s.replace('``true``', '``True``')
s = s.replace('``false``', '``False``')
@ -130,24 +160,39 @@ def process_comment(comment):
wrapper = textwrap.TextWrapper()
wrapper.expand_tabs = True
wrapper.replace_whitespace = True
wrapper.width = 75
wrapper.drop_whitespace = True
wrapper.width = 70
wrapper.initial_indent = wrapper.subsequent_indent = ''
result = ''
for x in re.split(r'\n{2,}', s):
wrapped = wrapper.fill(x.strip())
if len(wrapped) > 0 and wrapped[0] == '$':
result += wrapped[1:] + '\n'
wrapper.initial_indent = wrapper.subsequent_indent = ' '*4
in_code_segment = False
for x in re.split(r'(```)', s):
if x == '```':
if not in_code_segment:
result += '```\n'
else:
result += '\n```\n\n'
in_code_segment = not in_code_segment
elif in_code_segment:
result += x.strip()
else:
result += wrapped + '\n\n'
wrapper.initial_indent = wrapper.subsequent_indent = ''
return result.rstrip()
for y in re.split(r'(?: *\n *){2,}', x):
wrapped = wrapper.fill(re.sub(r'\s+', ' ', y).strip())
if len(wrapped) > 0 and wrapped[0] == '$':
result += wrapped[1:] + '\n'
wrapper.initial_indent = \
wrapper.subsequent_indent = ' ' * 4
else:
if len(wrapped) > 0:
result += wrapped + '\n\n'
wrapper.initial_indent = wrapper.subsequent_indent = ''
return result.rstrip().lstrip('\n')
def extract(filename, node, prefix, output):
num_extracted = 0
if not (node.location.file is None or os.path.samefile(d(node.location.file.name), filename)):
if not (node.location.file is None or
os.path.samefile(d(node.location.file.name), filename)):
return 0
if node.kind in RECURSE_LIST:
sub_prefix = prefix
@ -162,13 +207,19 @@ def extract(filename, node, prefix, output):
if node.kind in PRINT_LIST:
comment = d(node.raw_comment) if node.raw_comment is not None else ''
comment = process_comment(comment)
name = sanitize_name(prefix + '_' + d(node.spelling))
output.append('\nstatic const char *%s = %sR"doc(%s)doc";' % (name, '\n' if '\n' in comment else '', comment))
num_extracted += 1
sub_prefix = prefix
if len(sub_prefix) > 0:
sub_prefix += '_'
if len(node.spelling) > 0:
name = sanitize_name(sub_prefix + d(node.spelling))
output.append('\nstatic const char *%s =%sR"doc(%s)doc";' %
(name, '\n' if '\n' in comment else ' ', comment))
num_extracted += 1
return num_extracted
class ExtractionThread(Thread):
def __init__ (self, filename, parameters, output):
def __init__(self, filename, parameters, output):
Thread.__init__(self)
self.filename = filename
self.parameters = parameters
@ -176,9 +227,10 @@ class ExtractionThread(Thread):
job_semaphore.acquire()
def run(self):
print('Processing "%s" ..' % self.filename, file = sys.stderr)
print('Processing "%s" ..' % self.filename, file=sys.stderr)
try:
index = cindex.Index(cindex.conf.lib.clang_createIndex(False, True))
index = cindex.Index(
cindex.conf.lib.clang_createIndex(False, True))
tu = index.parse(self.filename, self.parameters)
extract(self.filename, tu.cursor, '', self.output)
finally:
@ -188,6 +240,20 @@ if __name__ == '__main__':
parameters = ['-x', 'c++', '-std=c++11']
filenames = []
if platform.system() == 'Darwin':
dev_path = '/Applications/Xcode.app/Contents/Developer/'
lib_dir = dev_path + 'Toolchains/XcodeDefault.xctoolchain/usr/lib/'
sdk_dir = dev_path + 'Platforms/MacOSX.platform/Developer/SDKs'
libclang = lib_dir + 'libclang.dylib'
if os.path.exists(libclang):
cindex.Config.set_library_path(os.path.dirname(libclang))
if os.path.exists(sdk_dir):
sysroot_dir = os.path.join(sdk_dir, next(os.walk(sdk_dir))[1][0])
parameters.append('-isysroot')
parameters.append(sysroot_dir)
for item in sys.argv[1:]:
if item.startswith('-'):
parameters.append(item)
@ -203,17 +269,19 @@ if __name__ == '__main__':
Do not edit! These were automatically extracted by mkdoc.py
*/
#define __EXPAND(x) x
#define __COUNT(_1, _2, _3, _4, _5, COUNT, ...) COUNT
#define __VA_SIZE(...) __EXPAND(__COUNT(__VA_ARGS__, 5, 4, 3, 2, 1))
#define __CAT1(a, b) a ## b
#define __CAT2(a, b) __CAT1(a, b)
#define __DOC1(n1) __doc_##n1
#define __DOC2(n1, n2) __doc_##n1##_##n2
#define __DOC3(n1, n2, n3) __doc_##n1##_##n2##_##n3
#define __DOC4(n1, n2, n3, n4) __doc_##n1##_##n2##_##n3##_##n4
#define __DOC5(n1, n2, n3, n4, n5) __doc_##n1##_##n2##_##n3##_##n4_##n5
#define DOC(...) __EXPAND(__EXPAND(__CAT2(__DOC, __VA_SIZE(__VA_ARGS__)))(__VA_ARGS__))
#define __EXPAND(x) x
#define __COUNT(_1, _2, _3, _4, _5, _6, _7, COUNT, ...) COUNT
#define __VA_SIZE(...) __EXPAND(__COUNT(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1))
#define __CAT1(a, b) a ## b
#define __CAT2(a, b) __CAT1(a, b)
#define __DOC1(n1) __doc_##n1
#define __DOC2(n1, n2) __doc_##n1##_##n2
#define __DOC3(n1, n2, n3) __doc_##n1##_##n2##_##n3
#define __DOC4(n1, n2, n3, n4) __doc_##n1##_##n2##_##n3##_##n4
#define __DOC5(n1, n2, n3, n4, n5) __doc_##n1##_##n2##_##n3##_##n4##_##n5
#define __DOC6(n1, n2, n3, n4, n5, n6) __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6
#define __DOC7(n1, n2, n3, n4, n5, n6, n7) __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6##_##n7
#define DOC(...) __EXPAND(__EXPAND(__CAT2(__DOC, __VA_SIZE(__VA_ARGS__)))(__VA_ARGS__))
#if defined(__GNUG__)
#pragma GCC diagnostic push
@ -226,7 +294,7 @@ if __name__ == '__main__':
thr = ExtractionThread(filename, parameters, output)
thr.start()
print('Waiting for jobs to finish ..', file = sys.stderr)
print('Waiting for jobs to finish ..', file=sys.stderr)
for i in range(job_count):
job_semaphore.acquire()

|||||||
100:0
Loading…
Cancel
Save