Merge branch 'cygwin' of https://github.com/BorisSchaeling/pybind11 into BorisSchaeling-cygwin
diff --git a/.travis.yml b/.travis.yml
index e523197..b0d8a0e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,6 +9,7 @@
sources:
- ubuntu-toolchain-r-test
- deadsnakes
+ - kubuntu-backports # cmake 2.8.12
packages:
- g++-4.8
- g++-4.8-multilib
@@ -17,6 +18,7 @@
- python3.5-dev
- python3.5-venv
- python3.5-dev:i386
+ - cmake
matrix:
include:
- os: linux
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0452d5d..b255045 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,240 +5,165 @@
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(pybind11)
-option(PYBIND11_INSTALL "Install pybind11 header files?" ON)
+# Check if pybind11 is being used directly or via add_subdirectory
+set(PYBIND11_MASTER_PROJECT OFF)
+if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+ set(PYBIND11_MASTER_PROJECT ON)
+endif()
+
+option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT})
+option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT})
# Add a CMake parameter for choosing a desired Python version
set(PYBIND11_PYTHON_VERSION "" CACHE STRING "Python version to use for compiling the example application")
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/tools")
+set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6 3.7)
+find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} REQUIRED)
+
include(CheckCXXCompilerFlag)
-# 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)
- set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
- "MinSizeRel" "RelWithDebInfo")
-endif()
-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)
- find_package(PythonLibs ${PYBIND11_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 line to work
-string(REPLACE "+" "" PYTHONLIBS_VERSION_STRING "+${PYTHONLIBS_VERSION_STRING}")
-find_package(PythonInterp ${PYTHONLIBS_VERSION_STRING} EXACT REQUIRED)
-
-if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Intel")
- CHECK_CXX_COMPILER_FLAG("-std=c++14" HAS_CPP14_FLAG)
- CHECK_CXX_COMPILER_FLAG("-std=c++11" HAS_CPP11_FLAG)
+if(NOT MSVC AND NOT PYBIND11_CPP_STANDARD)
+ check_cxx_compiler_flag("-std=c++14" HAS_CPP14_FLAG)
+ check_cxx_compiler_flag("-std=c++11" HAS_CPP11_FLAG)
if (HAS_CPP14_FLAG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
+ set(PYBIND11_CPP_STANDARD -std=c++14)
elseif (HAS_CPP11_FLAG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ set(PYBIND11_CPP_STANDARD -std=c++11)
else()
message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!")
endif()
- # Enable link time optimization and set the default symbol
- # visibility to hidden (very important to obtain small binaries)
- if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
- # Default symbol visibility
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
+ set(PYBIND11_CPP_STANDARD ${PYBIND11_CPP_STANDARD} CACHE STRING
+ "C++ standard flag, e.g. -std=c++11 or -std=c++14. Defaults to latest available.")
+endif()
- # Check for Link Time Optimization support
- # (GCC/Clang)
- CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
- if (HAS_LTO_FLAG AND NOT CYGWIN)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
- endif()
+# Cache variables so pybind11_add_module can be used in parent projects
+set(PYBIND11_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/include" CACHE INTERNAL "")
+set(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS} CACHE INTERNAL "")
+set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} CACHE INTERNAL "")
+set(PYTHON_MODULE_PREFIX ${PYTHON_MODULE_PREFIX} CACHE INTERNAL "")
+set(PYTHON_MODULE_EXTENSION ${PYTHON_MODULE_EXTENSION} CACHE INTERNAL "")
- # Intel equivalent to LTO is called IPO
- if (CMAKE_CXX_COMPILER_ID MATCHES "Intel")
- CHECK_CXX_COMPILER_FLAG("-ipo" HAS_IPO_FLAG)
- if (HAS_IPO_FLAG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ipo")
+# Build a Python extension module:
+# pybind11_add_module(<name> source1 [source2 ...])
+#
+function(pybind11_add_module target_name)
+ add_library(${target_name} MODULE ${ARGN})
+ target_include_directories(${target_name} PUBLIC ${PYBIND11_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS})
+
+ # The prefix and extension are provided by FindPythonLibsNew.cmake
+ set_target_properties(${target_name} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}")
+ set_target_properties(${target_name} PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}")
+
+ if(WIN32)
+ # Link against the Python shared library on Windows
+ target_link_libraries(${target_name} PRIVATE ${PYTHON_LIBRARIES})
+ elseif(APPLE)
+ # It's quite common to have multiple copies of the same Python version
+ # installed on one's system. E.g.: one copy from the OS and another copy
+ # that's statically linked into an application like Blender or Maya.
+ # If we link our plugin library against the OS Python here and import it
+ # into Blender or Maya later on, this will cause segfaults when multiple
+ # conflicting Python instances are active at the same time (even when they
+ # are of the same version).
+
+ # Windows is not affected by this issue since it handles DLL imports
+ # differently. The solution for Linux and Mac OS is simple: we just don't
+ # link against the Python library. The resulting shared library will have
+ # missing symbols, but that's perfectly fine -- they will be resolved at
+ # import time.
+
+ target_link_libraries(${target_name} PRIVATE "-undefined dynamic_lookup")
+ endif()
+
+ if(NOT MSVC)
+ # Make sure C++11/14 are enabled
+ target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD})
+
+ # Enable link time optimization and set the default symbol
+ # visibility to hidden (very important to obtain small binaries)
+ string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE)
+ if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
+ # Check for Link Time Optimization support (GCC/Clang)
+ check_cxx_compiler_flag("-flto" HAS_LTO_FLAG)
+ if(HAS_LTO_FLAG AND NOT CYGWIN)
+ target_compile_options(${target_name} PRIVATE -flto)
+ endif()
+
+ # Intel equivalent to LTO is called IPO
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
+ check_cxx_compiler_flag("-ipo" HAS_IPO_FLAG)
+ if(HAS_IPO_FLAG)
+ target_compile_options(${target_name} PRIVATE -ipo)
+ endif()
+ endif()
+
+ # Default symbol visibility
+ target_compile_options(${target_name} PRIVATE "-fvisibility=hidden")
+
+ # Strip unnecessary sections of the binary on Linux/Mac OS
+ if(CMAKE_STRIP)
+ if(APPLE)
+ add_custom_command(TARGET ${target_name} POST_BUILD
+ COMMAND ${CMAKE_STRIP} -u -r $<TARGET_FILE:${target_name}>)
+ else()
+ add_custom_command(TARGET ${target_name} POST_BUILD
+ COMMAND ${CMAKE_STRIP} $<TARGET_FILE:${target_name}>)
+ endif()
endif()
endif()
- endif()
-endif()
-
-# Compile with compiler warnings turned on
-if(MSVC)
- if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
- string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- else()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
- endif()
-elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion")
-endif()
-
-
-# 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
-)
-
-set(PYBIND11_EXAMPLES
- example/example1.cpp
- example/example2.cpp
- example/example3.cpp
- example/example4.cpp
- example/example5.cpp
- example/example6.cpp
- example/example7.cpp
- example/example8.cpp
- example/example9.cpp
- example/example10.cpp
- example/example11.cpp
- example/example12.cpp
- example/example13.cpp
- 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}
- example/example.cpp
- ${PYBIND11_EXAMPLES}
-)
-
-# Link against the Python shared library
-target_link_libraries(example ${PYTHON_LIBRARY})
-
-# Don't add a 'lib' prefix to the shared library
-set_target_properties(example PROPERTIES PREFIX "")
-
-# Always write the output file directly into the 'example' directory (even on MSVC)
-set(CompilerFlags
- LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_RELEASE LIBRARY_OUTPUT_DIRECTORY_DEBUG
- LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO
- RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_RELEASE RUNTIME_OUTPUT_DIRECTORY_DEBUG
- RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO)
-
-foreach(CompilerFlag ${CompilerFlags})
- set_target_properties(example PROPERTIES ${CompilerFlag} ${PROJECT_SOURCE_DIR}/example)
-endforeach()
-
-if (WIN32)
- if (MSVC)
+ elseif(MSVC)
# /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 ")
+ target_compile_options(${target_name} PRIVATE /MP /bigobj)
+
+ # Enforce link time code generation on MSVC, except in debug mode
+ target_compile_options(${target_name} PRIVATE $<$<NOT:$<CONFIG:Debug>>:/GL>)
+
+ # Fancy generator expressions don't work with linker flags, for reasons unknown
+ set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE /LTCG)
+ set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL /LTCG)
+ set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS_RELWITHDEBINFO /LTCG)
endif()
+endfunction()
- # .PYD file extension on Windows
- set_target_properties(example PROPERTIES SUFFIX ".pyd")
-elseif (UNIX)
- # It's quite common to have multiple copies of the same Python version
- # installed on one's system. E.g.: one copy from the OS and another copy
- # that's statically linked into an application like Blender or Maya.
- # If we link our plugin library against the OS Python here and import it
- # into Blender or Maya later on, this will cause segfaults when multiple
- # conflicting Python instances are active at the same time (even when they
- # are of the same version).
-
- # Windows is not affected by this issue since it handles DLL imports
- # differently. The solution for Linux and Mac OS is simple: we just don't
- # link against the Python library. The resulting shared library will have
- # missing symbols, but that's perfectly fine -- they will be resolved at
- # import time.
-
- # .DLL file extension on Cygwin, .SO file extension on Linux/Mac OS
- if (CYGWIN)
- set(SUFFIX ".dll")
+# Compile with compiler warnings turned on
+function(pybind11_enable_warnings target_name)
+ if(MSVC)
+ target_compile_options(${target_name} PRIVATE /W4)
else()
- set(SUFFIX ".so")
+ target_compile_options(${target_name} PRIVATE -Wall -Wextra -Wconversion)
endif()
- set_target_properties(example PROPERTIES SUFFIX ${SUFFIX})
+endfunction()
- # Optimize for a small binary size
- if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
- set_target_properties(example PROPERTIES COMPILE_FLAGS "-Os")
- endif()
-
- # Strip unnecessary sections of the binary on Linux/Mac OS
- if(APPLE)
- 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_SOURCE_DIR}/example/example${SUFFIX})
- endif()
- else()
- if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
- add_custom_command(TARGET example POST_BUILD COMMAND strip ${PROJECT_SOURCE_DIR}/example/example${SUFFIX})
- endif()
- endif()
+if (PYBIND11_TEST)
+ enable_testing()
+ add_subdirectory(example)
endif()
-enable_testing()
-
-set(RUN_TEST ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/run_test.py)
-if (MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Intel")
- set(RUN_TEST ${RUN_TEST} --relaxed)
-endif()
-
-foreach(VALUE ${PYBIND11_EXAMPLES})
- string(REGEX REPLACE "^example/(.+).cpp$" "\\1" EXAMPLE_NAME "${VALUE}")
- add_test(NAME ${EXAMPLE_NAME} COMMAND ${RUN_TEST} ${EXAMPLE_NAME})
-endforeach()
-
if (PYBIND11_INSTALL)
- install(FILES ${PYBIND11_HEADERS} DESTINATION include/pybind11)
+ 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
+ )
+
+ install(FILES ${PYBIND11_HEADERS} DESTINATION include/pybind11)
endif()
diff --git a/README.md b/README.md
index 376f562..d9505ac 100644
--- a/README.md
+++ b/README.md
@@ -90,6 +90,7 @@
2. GCC (any non-ancient version with C++11 support)
3. Microsoft Visual Studio 2015 or newer
4. Intel C++ compiler v15 or newer
+5. Cygwin
## About
@@ -101,8 +102,10 @@
@hulucc,
Sergey Lyskov
Johan Mabille,
-Tomasz Miąsko, and
-Ben Pritchard.
+Tomasz Miąsko,
+Dean Moldovan,
+Ben Pritchard, and
+Boris Schäling.
### License
diff --git a/docs/advanced.rst b/docs/advanced.rst
index 4353536..ba95c20 100644
--- a/docs/advanced.rst
+++ b/docs/advanced.rst
@@ -268,8 +268,14 @@
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
@@ -277,9 +283,8 @@
PYBIND11_PLUGIN(example) {
py::module m("example", "pybind11 example plugin");
- py::class_<PyAnimal> animal(m, "Animal");
+ py::class_<Animal, std::unique_ptr<Animal>, PyAnimal /* <--- trampoline*/> animal(m, "Animal");
animal
- .alias<Animal>()
.def(py::init<>())
.def("go", &Animal::go);
@@ -291,10 +296,10 @@
return m.ptr();
}
-Importantly, the trampoline helper class is used as the template argument to
-:class:`class_`, and a call to :func:`class_::alias` informs the binding
-generator that this is merely an alias for the underlying type ``Animal``.
-Following this, we are able to define a constructor as usual.
+Importantly, pybind11 is made aware of the trampoline trampoline helper class
+by specifying it as the *third* template argument to :class:`class_`. The
+second argument with the unique pointer is simply the default holder type used
+by pybind11. Following this, we are able to define a constructor as usual.
The Python session below shows how to override ``Animal::go`` and invoke it via
a virtual method call.
@@ -315,12 +320,12 @@
.. 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.
+ The :func:`PYBIND11_OVERLOAD_*` calls are all just 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::
@@ -363,9 +368,8 @@
PYBIND11_PLUGIN(example) {
py::module m("example", "pybind11 example plugin");
- py::class_<PyAnimal> animal(m, "Animal");
+ py::class_<Animal, std::unique_ptr<Animal>, PyAnimal> animal(m, "Animal");
animal
- .alias<Animal>()
.def(py::init<>())
.def("go", &Animal::go);
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 632f2be..7cf26e1 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -5,9 +5,11 @@
1.8 (Not yet released)
----------------------
+* Redesigned virtual call mechanism and user-facing syntax (breaking change!)
* Prevent implicit conversion of floating point values to integral types in
function arguments
* Transparent conversion of sparse and dense Eigen data types
+* ``std::vector<>`` type bindings analogous to Boost.Python's ``indexing_suite``
* Fixed incorrect default return value policy for functions returning a shared
pointer
* Don't allow casting a ``None`` value into a C++ lvalue reference
@@ -16,10 +18,19 @@
* Extended ``str`` type to also work with ``bytes`` instances
* Added ``[[noreturn]]`` attribute to ``pybind11_fail()`` to quench some
compiler warnings
+* List function arguments in exception text when the dispatch code cannot find
+ a matching overload
* Various minor ``iterator`` and ``make_iterator()`` improvements
+* Transparently support ``__bool__`` on Python 2.x and Python 3.x
+* Fixed issue with destructor of unpickled object not being called
* Minor CMake build system improvements on Windows
* Many ``mkdoc.py`` improvements (enumerations, template arguments, ``DOC()``
macro accepts more arguments)
+* New ``pybind11::args`` and ``pybind11::kwargs`` types to create functions which
+ take an arbitrary number of arguments and keyword arguments
+* New syntax to call a Python function from C++ using ``*args`` and ``*kwargs``
+* Added an ``ExtraFlags`` template argument to the NumPy ``array_t<>`` wrapper. This
+ can be used to disable an enforced cast that may lose precision
* Documentation improvements (pickling support, ``keep_alive``)
1.7 (April 30, 2016)
diff --git a/docs/compiling.rst b/docs/compiling.rst
index 5f4d098..5800694 100644
--- a/docs/compiling.rst
+++ b/docs/compiling.rst
@@ -26,146 +26,28 @@
Building with CMake
===================
-For C++ codebases that already have an existing CMake-based build system, the
-following snippet should be a good starting point to create bindings across
-platforms. It assumes that the code is located in a file named
-:file:`example.cpp`, and that the pybind11 repository is located in a
-subdirectory named :file:`pybind11`.
+For C++ codebases that have an existing CMake-based build system, a Python
+extension module can be created with just a few lines of code:
.. code-block:: cmake
- cmake_minimum_required(VERSION 2.8)
-
+ cmake_minimum_required(VERSION 2.8.12)
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")
+ add_subdirectory(pybind11)
+ pybind11_add_module(example example.cpp)
- include(CheckCXXCompilerFlag)
+This assumes that the pybind11 repository is located in a subdirectory named
+:file:`pybind11` and that the code is located in a file named :file:`example.cpp`.
+The CMake command ``add_subdirectory`` will import a function with the signature
+``pybind11_add_module(<name> source1 [source2 ...])``. It will take care of all
+the details needed to build a Python extension module on any platform.
- # 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)
- set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
- "MinSizeRel" "RelWithDebInfo")
- endif()
- string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE)
+The target Python version can be selected by setting the ``PYBIND11_PYTHON_VERSION``
+variable before adding the pybind11 subdirectory. Alternatively, an exact Python
+installation can be specified by setting ``PYTHON_EXECUTABLE``.
- # Try to autodetect Python (can be overridden manually if needed)
- 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)
- find_package(PythonLibs ${EXAMPLE_PYTHON_VERSION} REQUIRED)
- endif()
- else()
- find_package(PythonLibs REQUIRED)
- endif()
+A working sample project, including a way to invoke CMake from :file:`setup.py` for
+PyPI integration, can be found in the [cmake_example]_ repository.
- # 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
- # find_package(PythonInterp ${PYTHONLIBS_VERSION_STRING} EXACT REQUIRED)
-
- if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
- CHECK_CXX_COMPILER_FLAG("-std=c++14" HAS_CPP14_FLAG)
- CHECK_CXX_COMPILER_FLAG("-std=c++11" HAS_CPP11_FLAG)
-
- if (HAS_CPP14_FLAG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
- elseif (HAS_CPP11_FLAG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
- else()
- message(FATAL_ERROR "Unsupported compiler -- at least C++11 support is needed!")
- endif()
-
- # Enable link time optimization and set the default symbol
- # visibility to hidden (very important to obtain small binaries)
- if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
- # Default symbol visibility
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
-
- # Check for Link Time Optimization support
- CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
- if (HAS_LTO_FLAG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
- endif()
- endif()
- endif()
-
- # 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_directories(${PROJECT_SOURCE_DIR}/pybind11/include)
-
- # Create the binding library
- add_library(example SHARED
- example.cpp
- # ... extra files go here ...
- )
-
- # Don't add a 'lib' prefix to the shared library
- set_target_properties(example PROPERTIES PREFIX "")
-
- if (WIN32)
- if (MSVC)
- # /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
- set_target_properties(example PROPERTIES SUFFIX ".pyd")
-
- # Link against the Python shared library
- target_link_libraries(example ${PYTHON_LIBRARY})
- elseif (UNIX)
- # It's quite common to have multiple copies of the same Python version
- # installed on one's system. E.g.: one copy from the OS and another copy
- # that's statically linked into an application like Blender or Maya.
- # If we link our plugin library against the OS Python here and import it
- # into Blender or Maya later on, this will cause segfaults when multiple
- # conflicting Python instances are active at the same time (even when they
- # are of the same version).
-
- # Windows is not affected by this issue since it handles DLL imports
- # differently. The solution for Linux and Mac OS is simple: we just don't
- # link against the Python library. The resulting shared library will have
- # missing symbols, but that's perfectly fine -- they will be resolved at
- # import time.
-
- # .SO file extension on Linux/Mac OS
- set_target_properties(example PROPERTIES SUFFIX ".so")
-
- # Strip unnecessary sections of the binary on Linux/Mac OS
- if(APPLE)
- 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)
- endif()
- else()
- if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
- add_custom_command(TARGET example POST_BUILD
- COMMAND strip ${PROJECT_BINARY_DIR}/example.so)
- endif()
- endif()
- endif()
+.. [cmake_example] https://github.com/dean0x7d/pybind11_cmake_example
diff --git a/docs/conf.py b/docs/conf.py
index 9d25838..39d4933 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -56,9 +56,9 @@
# built documents.
#
# The short X.Y version.
-version = '1.0'
+version = '1.8'
# The full version, including alpha/beta/rc tags.
-release = '1.0'
+release = '1.8'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/release.rst b/docs/release.rst
index d8f9db8..1b24e33 100644
--- a/docs/release.rst
+++ b/docs/release.rst
@@ -2,7 +2,8 @@
- Update the version number and push to pypi
- Update ``pybind11/_version.py`` (set release version, remove 'dev')
- - Tag release date in ``doc/changelog.rst``.
+ - Update version in ``docs/conf.py``
+ - Tag release date in ``docs/changelog.rst``.
- ``git add`` and ``git commit``.
- ``git tag -a vX.Y -m 'vX.Y release'``.
- ``git push``
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
new file mode 100644
index 0000000..547dad7
--- /dev/null
+++ b/example/CMakeLists.txt
@@ -0,0 +1,68 @@
+# 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)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
+ "MinSizeRel" "RelWithDebInfo")
+endif()
+
+set(PYBIND11_EXAMPLES
+ example1.cpp
+ example2.cpp
+ example3.cpp
+ example4.cpp
+ example5.cpp
+ example6.cpp
+ example7.cpp
+ example8.cpp
+ example9.cpp
+ example10.cpp
+ example11.cpp
+ example12.cpp
+ example13.cpp
+ example14.cpp
+ example15.cpp
+ example16.cpp
+ example17.cpp
+ issues.cpp
+)
+
+# Check if Eigen is available
+find_package(Eigen3 QUIET)
+
+if(EIGEN3_FOUND)
+ list(APPEND PYBIND11_EXAMPLES eigen.cpp)
+ message(STATUS "Building Eigen testcase")
+else()
+ message(STATUS "NOT Building Eigen testcase")
+endif()
+
+# Create the binding library
+pybind11_add_module(example example.cpp ${PYBIND11_EXAMPLES})
+pybind11_enable_warnings(example)
+
+if(EIGEN3_FOUND)
+ target_include_directories(example PRIVATE ${EIGEN3_INCLUDE_DIR})
+ target_compile_definitions(example PRIVATE -DPYBIND11_TEST_EIGEN)
+endif()
+
+# Always write the output file directly into the 'example' directory (even on MSVC)
+set(CompilerFlags
+ LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_RELEASE LIBRARY_OUTPUT_DIRECTORY_DEBUG
+ LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO
+ RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_RELEASE RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO)
+
+foreach(CompilerFlag ${CompilerFlags})
+ set_target_properties(example PROPERTIES ${CompilerFlag} ${PROJECT_SOURCE_DIR}/example)
+endforeach()
+
+set(RUN_TEST ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/run_test.py)
+if(MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Intel")
+ set(RUN_TEST ${RUN_TEST} --relaxed)
+endif()
+
+foreach(VALUE ${PYBIND11_EXAMPLES})
+ string(REGEX REPLACE "^(.+).cpp$" "\\1" EXAMPLE_NAME "${VALUE}")
+ add_test(NAME ${EXAMPLE_NAME} COMMAND ${RUN_TEST} ${EXAMPLE_NAME})
+endforeach()
diff --git a/example/example11.cpp b/example/example11.cpp
index 466eed4..799fa62 100644
--- a/example/example11.cpp
+++ b/example/example11.cpp
@@ -27,8 +27,8 @@
}
void args_function(py::args args) {
- for (auto item : args)
- std::cout << "got argument: " << item << std::endl;
+ 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) {
diff --git a/example/example11.ref b/example/example11.ref
index 4c433b7..f4c23ae 100644
--- a/example/example11.ref
+++ b/example/example11.ref
@@ -29,7 +29,7 @@
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)
diff --git a/example/example12.cpp b/example/example12.cpp
index 5cc8dc8..e5555f5 100644
--- a/example/example12.cpp
+++ b/example/example12.cpp
@@ -82,15 +82,11 @@
}
void init_ex12(py::module &m) {
- /* Important: use the wrapper type as a template
- argument to class_<>, but use the original name
- to denote the type */
- py::class_<PyExample12>(m, "Example12")
- /* Declare that 'PyExample12' is really an alias for the original type 'Example12' */
- .alias<Example12>()
+ /* Important: indicate the trampoline class PyExample12 using the third
+ argument to py::class_. The second argument with the unique pointer
+ is simply the default holder type used by pybind11. */
+ py::class_<Example12, std::unique_ptr<Example12>, PyExample12>(m, "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)
diff --git a/example/example12.ref b/example/example12.ref
index 2274cdd..a25023f 100644
--- a/example/example12.ref
+++ b/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)
diff --git a/example/example14.ref b/example/example14.ref
index c18c7ad..44e6820 100644
--- a/example/example14.ref
+++ b/example/example14.ref
@@ -11,7 +11,7 @@
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 : 0x0
<example.StringList object at 0x10d3277a0>
diff --git a/example/example5.ref b/example/example5.ref
index bfc3cb2..a9c7d46 100644
--- a/example/example5.ref
+++ b/example/example5.ref
@@ -14,7 +14,7 @@
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
diff --git a/example/issues.cpp b/example/issues.cpp
index d1a1941..e164708 100644
--- a/example/issues.cpp
+++ b/example/issues.cpp
@@ -42,8 +42,7 @@
}
};
- py::class_<DispatchIssue> base(m2, "DispatchIssue");
- base.alias<Base>()
+ py::class_<Base, std::unique_ptr<Base>, DispatchIssue>(m2, "DispatchIssue")
.def(py::init<>())
.def("dispatch", &Base::dispatch);
@@ -108,4 +107,28 @@
// (no id): don't cast doubles to ints
m2.def("expect_float", [](float f) { return f; });
m2.def("expect_int", [](int i) { return i; });
+
+ // (no id): don't invoke Python dispatch code when instantiating C++
+ // classes that were not extended on the Python side
+ struct A {
+ virtual ~A() {}
+ virtual void f() { std::cout << "A.f()" << std::endl; }
+ };
+
+ struct PyA : A {
+ PyA() { std::cout << "PyA.PyA()" << std::endl; }
+
+ void f() override {
+ std::cout << "PyA.f()" << std::endl;
+ PYBIND11_OVERLOAD(void, A, f);
+ }
+ };
+
+ auto call_f = [](A *a) { a->f(); };
+
+ pybind11::class_<A, std::unique_ptr<A>, PyA>(m2, "A")
+ .def(py::init<>())
+ .def("f", &A::f);
+
+ m2.def("call_f", call_f);
}
diff --git a/example/issues.py b/example/issues.py
index d075e83..257f08e 100644
--- a/example/issues.py
+++ b/example/issues.py
@@ -9,6 +9,7 @@
from example.issues import iterator_passthrough
from example.issues import ElementList, ElementA, print_element
from example.issues import expect_float, expect_int
+from example.issues import A, call_f
import gc
print_cchar("const char *")
@@ -55,3 +56,19 @@
print("Failed as expected: " + str(e))
print(expect_float(12))
+
+class B(A):
+ def __init__(self):
+ super(B, self).__init__()
+
+ def f(self):
+ print("In python f()")
+
+print("C++ version")
+a = A()
+call_f(a)
+
+print("Python version")
+b = B()
+call_f(b)
+
diff --git a/example/issues.ref b/example/issues.ref
index af61939..58cc798 100644
--- a/example/issues.ref
+++ b/example/issues.ref
@@ -1,14 +1,20 @@
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
+C++ version
+A.f()
+Python version
+PyA.PyA()
+PyA.f()
+In python f()
diff --git a/include/pybind11/attr.h b/include/pybind11/attr.h
index d63a44e..5e2d8f2 100644
--- a/include/pybind11/attr.h
+++ b/include/pybind11/attr.h
@@ -65,6 +65,7 @@
struct undefined_t;
template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_;
template <typename... Args> struct init;
+template <typename... Args> struct init_alias;
inline void keep_alive_impl(int Nurse, int Patient, handle args, handle ret);
/// Internal data structure which holds metadata about a keyword argument
diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h
index 31f5cb5..def3044 100644
--- a/include/pybind11/cast.h
+++ b/include/pybind11/cast.h
@@ -660,7 +660,7 @@
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());
}
diff --git a/include/pybind11/eigen.h b/include/pybind11/eigen.h
index 00f0347..96daf48 100644
--- a/include/pybind11/eigen.h
+++ b/include/pybind11/eigen.h
@@ -133,7 +133,7 @@
operator Type*() { return &value; }
operator Type&() { return value; }
-private:
+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>
@@ -143,7 +143,7 @@
template <typename T = Type, typename std::enable_if<T::ColsAtCompileTime != Eigen::Dynamic, int>::type = 0>
static PYBIND11_DESCR cols() { return _<T::ColsAtCompileTime>(); }
-private:
+protected:
Type value;
};
@@ -269,7 +269,7 @@
operator Type*() { return &value; }
operator Type&() { return value; }
-private:
+protected:
Type value;
};
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
index 46923de..7ac9e5c 100644
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -422,6 +422,14 @@
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) {
@@ -495,7 +503,7 @@
NAMESPACE_BEGIN(detail)
/// Generic support for creating new Python heap types
class generic_type : public object {
- template <typename type, typename holder_type> friend class class_;
+ template <typename type, typename holder_type, typename type_alias> friend class class_;
public:
PYBIND11_OBJECT_DEFAULT(generic_type, object, PyType_Check)
protected:
@@ -713,7 +721,7 @@
};
NAMESPACE_END(detail)
-template <typename type, typename holder_type = std::unique_ptr<type>>
+template <typename type, typename holder_type = std::unique_ptr<type>, typename type_alias = type>
class class_ : public detail::generic_type {
public:
typedef detail::instance<type, holder_type> instance_type;
@@ -735,6 +743,11 @@
detail::process_attributes<Extra...>::init(extra..., &record);
detail::generic_type::initialize(&record);
+
+ if (!std::is_same<type, type_alias>::value) {
+ auto &instances = pybind11::detail::get_internals().registered_types_cpp;
+ instances[std::type_index(typeid(type_alias))] = instances[std::type_index(typeid(type))];
+ }
}
template <typename Func, typename... Extra>
@@ -772,6 +785,12 @@
return *this;
}
+ template <typename... Args, typename... Extra>
+ class_ &def(const detail::init_alias<Args...> &init, const Extra&... extra) {
+ init.template execute<type>(*this, extra...);
+ return *this;
+ }
+
template <typename Func> class_& def_buffer(Func &&func) {
struct capture { Func func; };
capture *ptr = new capture { std::forward<Func>(func) };
@@ -848,11 +867,6 @@
return *this;
}
- template <typename target> class_ alias() {
- auto &instances = pybind11::detail::get_internals().registered_types_cpp;
- instances[std::type_index(typeid(target))] = instances[std::type_index(typeid(type))];
- return *this;
- }
private:
/// Initialize holder object, variant 1: object derives from enable_shared_from_this
template <typename T>
@@ -951,9 +965,31 @@
NAMESPACE_BEGIN(detail)
template <typename... Args> struct init {
- template <typename Base, typename Holder, typename... Extra> void execute(pybind11::class_<Base, Holder> &class_, const Extra&... extra) const {
+ template <typename Base, typename Holder, typename Alias, typename... Extra,
+ typename std::enable_if<std::is_same<Base, Alias>::value, int>::type = 0>
+ void execute(pybind11::class_<Base, Holder, Alias> &class_, const Extra&... extra) const {
/// Function which calls a specific C++ in-place constructor
- class_.def("__init__", [](Base *instance, Args... args) { new (instance) Base(args...); }, extra...);
+ class_.def("__init__", [](Base *self_, Args... args) { new (self_) Base(args...); }, extra...);
+ }
+
+ template <typename Base, typename Holder, typename Alias, typename... Extra,
+ typename std::enable_if<!std::is_same<Base, Alias>::value &&
+ std::is_constructible<Base, Args...>::value, int>::type = 0>
+ void execute(pybind11::class_<Base, Holder, Alias> &class_, const Extra&... extra) const {
+ handle cl_type = class_;
+ class_.def("__init__", [cl_type](handle self_, Args... args) {
+ if (self_.get_type() == cl_type)
+ new (self_.cast<Base *>()) Base(args...);
+ else
+ new (self_.cast<Alias *>()) Alias(args...);
+ }, extra...);
+ }
+
+ template <typename Base, typename Holder, typename Alias, typename... Extra,
+ typename std::enable_if<!std::is_same<Base, Alias>::value &&
+ !std::is_constructible<Base, Args...>::value, int>::type = 0>
+ void execute(pybind11::class_<Base, Holder, Alias> &class_, const Extra&... extra) const {
+ class_.def("__init__", [](Alias *self, Args... args) { new (self) Alias(args...); }, extra...);
}
};
@@ -1038,6 +1074,11 @@
* can be handy to prevent cases where callbacks issued from an external
* thread would otherwise constantly construct and destroy thread state data
* structures.
+ *
+ * See the Python bindings of NanoGUI (http://github.com/wjakob/nanogui) for an
+ * example which uses features 2 and 3 to migrate the Python thread of
+ * execution to another thread (to run the event loop on the original thread,
+ * in this case).
*/
class gil_scoped_acquire {
@@ -1176,19 +1217,25 @@
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(__VA_ARGS__).template cast<ret_type>(); }
-#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_NAME(ret_type, cname, name, fn, ...) \
+ PYBIND11_OVERLOAD_INT(ret_type, name, __VA_ARGS__) \
+ return cname::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_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, cname, fn, ...) \
+ PYBIND11_OVERLOAD_NAME(ret_type, cname, #fn, fn, __VA_ARGS__)
+
+#define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \
+ PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, #fn, fn, __VA_ARGS__)
NAMESPACE_END(pybind11)
diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h
index c8f1cac..2ba03c0 100644
--- a/include/pybind11/pytypes.h
+++ b/include/pybind11/pytypes.h
@@ -323,10 +323,10 @@
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 detail::accessor handle::operator[](handle key) const { return detail::accessor(*this, key, false); }
+inline detail::accessor handle::operator[](const char *key) const { return detail::accessor(*this, key, false); }
+inline detail::accessor handle::attr(handle key) const { return detail::accessor(*this, key, true); }
+inline detail::accessor handle::attr(const char *key) const { return detail::accessor(*this, key, true); }
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); }
@@ -491,7 +491,7 @@
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 {
@@ -501,7 +501,7 @@
if (!m_ptr) pybind11_fail("Could not allocate dict object!");
}
size_t size() const { return (size_t) PyDict_Size(m_ptr); }
- detail::dict_iterator begin() const { return (++detail::dict_iterator(ptr(), 0)); }
+ detail::dict_iterator begin() const { return (++detail::dict_iterator(*this, 0)); }
detail::dict_iterator end() const { return detail::dict_iterator(); }
void clear() const { PyDict_Clear(ptr()); }
};
@@ -517,7 +517,7 @@
void append(const object &object) const { PyList_Append(m_ptr, object.ptr()); }
};
-class args : public list { PYBIND11_OBJECT_DEFAULT(args, list, PyList_Check) };
+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 {
diff --git a/tools/FindPythonLibsNew.cmake b/tools/FindPythonLibsNew.cmake
new file mode 100644
index 0000000..c80432a
--- /dev/null
+++ b/tools/FindPythonLibsNew.cmake
@@ -0,0 +1,187 @@
+# - Find python libraries
+# This module finds the libraries corresponding to the Python interpeter
+# FindPythonInterp provides.
+# This code sets the following variables:
+#
+# PYTHONLIBS_FOUND - have the Python libs been found
+# PYTHON_PREFIX - path to the Python installation
+# PYTHON_LIBRARIES - path to the python library
+# PYTHON_INCLUDE_DIRS - path to where Python.h is found
+# PYTHON_SITE_PACKAGES - path to installation site-packages
+# PYTHON_IS_DEBUG - whether the Python interpreter is a debug build
+#
+# PYTHON_INCLUDE_PATH - path to where Python.h is found (deprecated)
+#
+# A function PYTHON_ADD_MODULE(<name> src1 src2 ... srcN) is defined
+# to build modules for python.
+#
+# Thanks to talljimbo for the patch adding the 'LDVERSION' config
+# variable usage.
+
+#=============================================================================
+# Copyright 2001-2009 Kitware, Inc.
+# Copyright 2012 Continuum Analytics, Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the names of Kitware, Inc., the Insight Software Consortium,
+# nor the names of their contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#=============================================================================
+
+
+# Use the Python interpreter to find the libs.
+if(PythonLibsNew_FIND_REQUIRED)
+ find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} REQUIRED)
+else()
+ find_package(PythonInterp ${PythonLibsNew_FIND_VERSION})
+endif()
+
+if(NOT PYTHONINTERP_FOUND)
+ set(PYTHONLIBS_FOUND FALSE)
+ return()
+endif()
+
+# According to http://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter
+# testing whether sys has the gettotalrefcount function is a reliable, cross-platform
+# way to detect a CPython debug interpreter.
+#
+# The library suffix is from the config var LDVERSION sometimes, otherwise
+# VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows.
+execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
+ "from distutils import sysconfig as s;import sys;import struct;
+print('.'.join(str(v) for v in sys.version_info));
+print(sys.prefix);
+print(s.get_python_inc(plat_specific=True));
+print(s.get_python_lib(plat_specific=True));
+print(s.get_config_var('SO'));
+print(hasattr(sys, 'gettotalrefcount')+0);
+print(struct.calcsize('@P'));
+print(s.get_config_var('LDVERSION') or s.get_config_var('VERSION'));
+"
+ RESULT_VARIABLE _PYTHON_SUCCESS
+ OUTPUT_VARIABLE _PYTHON_VALUES
+ ERROR_VARIABLE _PYTHON_ERROR_VALUE
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+if(NOT _PYTHON_SUCCESS MATCHES 0)
+ if(PythonLibsNew_FIND_REQUIRED)
+ message(FATAL_ERROR
+ "Python config failure:\n${_PYTHON_ERROR_VALUE}")
+ endif()
+ set(PYTHONLIBS_FOUND FALSE)
+ return()
+endif()
+
+# Convert the process output into a list
+string(REGEX REPLACE ";" "\\\\;" _PYTHON_VALUES ${_PYTHON_VALUES})
+string(REGEX REPLACE "\n" ";" _PYTHON_VALUES ${_PYTHON_VALUES})
+list(GET _PYTHON_VALUES 0 _PYTHON_VERSION_LIST)
+list(GET _PYTHON_VALUES 1 PYTHON_PREFIX)
+list(GET _PYTHON_VALUES 2 PYTHON_INCLUDE_DIR)
+list(GET _PYTHON_VALUES 3 PYTHON_SITE_PACKAGES)
+list(GET _PYTHON_VALUES 4 PYTHON_MODULE_EXTENSION)
+list(GET _PYTHON_VALUES 5 PYTHON_IS_DEBUG)
+list(GET _PYTHON_VALUES 6 PYTHON_SIZEOF_VOID_P)
+list(GET _PYTHON_VALUES 7 PYTHON_LIBRARY_SUFFIX)
+
+# Make sure the Python has the same pointer-size as the chosen compiler
+# Skip if CMAKE_SIZEOF_VOID_P is not defined
+if(CMAKE_SIZEOF_VOID_P AND (NOT "${PYTHON_SIZEOF_VOID_P}" STREQUAL "${CMAKE_SIZEOF_VOID_P}"))
+ if(PythonLibsNew_FIND_REQUIRED)
+ math(EXPR _PYTHON_BITS "${PYTHON_SIZEOF_VOID_P} * 8")
+ math(EXPR _CMAKE_BITS "${CMAKE_SIZEOF_VOID_P} * 8")
+ message(FATAL_ERROR
+ "Python config failure: Python is ${_PYTHON_BITS}-bit, "
+ "chosen compiler is ${_CMAKE_BITS}-bit")
+ endif()
+ set(PYTHONLIBS_FOUND FALSE)
+ return()
+endif()
+
+# The built-in FindPython didn't always give the version numbers
+string(REGEX REPLACE "\\." ";" _PYTHON_VERSION_LIST ${_PYTHON_VERSION_LIST})
+list(GET _PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR)
+list(GET _PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR)
+list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH)
+
+# Make sure all directory separators are '/'
+string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX ${PYTHON_PREFIX})
+string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR})
+string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES})
+
+# TODO: All the nuances of CPython debug builds have not been dealt with/tested.
+if(PYTHON_IS_DEBUG)
+ set(PYTHON_MODULE_EXTENSION "_d${PYTHON_MODULE_EXTENSION}")
+endif()
+
+if(CMAKE_HOST_WIN32)
+ set(PYTHON_LIBRARY
+ "${PYTHON_PREFIX}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib")
+elseif(APPLE)
+ set(PYTHON_LIBRARY
+ "${PYTHON_PREFIX}/lib/libpython${PYTHON_LIBRARY_SUFFIX}.dylib")
+else()
+ if(${PYTHON_SIZEOF_VOID_P} MATCHES 8)
+ set(_PYTHON_LIBS_SEARCH "${PYTHON_PREFIX}/lib64" "${PYTHON_PREFIX}/lib")
+ else()
+ set(_PYTHON_LIBS_SEARCH "${PYTHON_PREFIX}/lib")
+ endif()
+ #message(STATUS "Searching for Python libs in ${_PYTHON_LIBS_SEARCH}")
+ # Probably this needs to be more involved. It would be nice if the config
+ # information the python interpreter itself gave us were more complete.
+ find_library(PYTHON_LIBRARY
+ NAMES "python${PYTHON_LIBRARY_SUFFIX}"
+ PATHS ${_PYTHON_LIBS_SEARCH}
+ NO_DEFAULT_PATH)
+
+ # If all else fails, just set the name/version and let the linker figure out the path.
+ if(NOT PYTHON_LIBRARY)
+ set(PYTHON_LIBRARY python${PYTHON_LIBRARY_SUFFIX})
+ endif()
+endif()
+
+# For backward compatibility, set PYTHON_INCLUDE_PATH, but make it internal.
+SET(PYTHON_INCLUDE_PATH "${PYTHON_INCLUDE_DIR}" CACHE INTERNAL
+ "Path to where Python.h is found (deprecated)")
+
+MARK_AS_ADVANCED(
+ PYTHON_LIBRARY
+ PYTHON_INCLUDE_DIR
+)
+
+# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the
+# cache entries because they are meant to specify the location of a single
+# library. We now set the variables listed by the documentation for this
+# module.
+SET(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
+SET(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
+SET(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}")
+
+find_package_message(PYTHON
+ "Found PythonLibs: ${PYTHON_LIBRARY}"
+ "${PYTHON_EXECUTABLE}${PYTHON_VERSION}")