mirror of
https://github.com/pybind/pybind11.git
synced 2025-02-16 21:57:55 +00:00
Merge branch 'pybind:master' into master
This commit is contained in:
commit
46e6ec6fa3
4
.github/workflows/emscripten.yaml
vendored
4
.github/workflows/emscripten.yaml
vendored
@ -5,6 +5,8 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- stable
|
||||
- v*
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@ -23,8 +25,6 @@ jobs:
|
||||
- uses: pypa/cibuildwheel@v2.20
|
||||
env:
|
||||
PYODIDE_BUILD_EXPORTS: whole_archive
|
||||
CFLAGS: -fexceptions
|
||||
LDFLAGS: -fexceptions
|
||||
with:
|
||||
package-dir: tests
|
||||
only: cp312-pyodide_wasm32
|
||||
|
2
.github/workflows/pip.yml
vendored
2
.github/workflows/pip.yml
vendored
@ -102,7 +102,7 @@ jobs:
|
||||
- uses: actions/download-artifact@v4
|
||||
|
||||
- name: Generate artifact attestation for sdist and wheel
|
||||
uses: actions/attest-build-provenance@210c1913531870065f03ce1f9440dd87bc0938cd # v1.4.0
|
||||
uses: actions/attest-build-provenance@310b0a4a3b0b78ef57ecda988ee04b132db73ef8 # v1.4.1
|
||||
with:
|
||||
subject-path: "*/pybind11*"
|
||||
|
||||
|
@ -9,12 +9,55 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define PYBIND11_HAS_TYPE_CASTER_STD_FUNCTION_SPECIALIZATIONS
|
||||
|
||||
#include "pybind11.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
PYBIND11_NAMESPACE_BEGIN(type_caster_std_function_specializations)
|
||||
|
||||
// ensure GIL is held during functor destruction
|
||||
struct func_handle {
|
||||
function f;
|
||||
#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17))
|
||||
// This triggers a syntax error under very special conditions (very weird indeed).
|
||||
explicit
|
||||
#endif
|
||||
func_handle(function &&f_) noexcept
|
||||
: f(std::move(f_)) {
|
||||
}
|
||||
func_handle(const func_handle &f_) { operator=(f_); }
|
||||
func_handle &operator=(const func_handle &f_) {
|
||||
gil_scoped_acquire acq;
|
||||
f = f_.f;
|
||||
return *this;
|
||||
}
|
||||
~func_handle() {
|
||||
gil_scoped_acquire acq;
|
||||
function kill_f(std::move(f));
|
||||
}
|
||||
};
|
||||
|
||||
// to emulate 'move initialization capture' in C++11
|
||||
struct func_wrapper_base {
|
||||
func_handle hfunc;
|
||||
explicit func_wrapper_base(func_handle &&hf) noexcept : hfunc(hf) {}
|
||||
};
|
||||
|
||||
template <typename Return, typename... Args>
|
||||
struct func_wrapper : func_wrapper_base {
|
||||
using func_wrapper_base::func_wrapper_base;
|
||||
Return operator()(Args... args) const {
|
||||
gil_scoped_acquire acq;
|
||||
// casts the returned object as a rvalue to the return type
|
||||
return hfunc.f(std::forward<Args>(args)...).template cast<Return>();
|
||||
}
|
||||
};
|
||||
|
||||
PYBIND11_NAMESPACE_END(type_caster_std_function_specializations)
|
||||
|
||||
template <typename Return, typename... Args>
|
||||
struct type_caster<std::function<Return(Args...)>> {
|
||||
@ -77,40 +120,8 @@ public:
|
||||
// See PR #1413 for full details
|
||||
}
|
||||
|
||||
// ensure GIL is held during functor destruction
|
||||
struct func_handle {
|
||||
function f;
|
||||
#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17))
|
||||
// This triggers a syntax error under very special conditions (very weird indeed).
|
||||
explicit
|
||||
#endif
|
||||
func_handle(function &&f_) noexcept
|
||||
: f(std::move(f_)) {
|
||||
}
|
||||
func_handle(const func_handle &f_) { operator=(f_); }
|
||||
func_handle &operator=(const func_handle &f_) {
|
||||
gil_scoped_acquire acq;
|
||||
f = f_.f;
|
||||
return *this;
|
||||
}
|
||||
~func_handle() {
|
||||
gil_scoped_acquire acq;
|
||||
function kill_f(std::move(f));
|
||||
}
|
||||
};
|
||||
|
||||
// to emulate 'move initialization capture' in C++11
|
||||
struct func_wrapper {
|
||||
func_handle hfunc;
|
||||
explicit func_wrapper(func_handle &&hf) noexcept : hfunc(std::move(hf)) {}
|
||||
Return operator()(Args... args) const {
|
||||
gil_scoped_acquire acq;
|
||||
// casts the returned object as a rvalue to the return type
|
||||
return hfunc.f(std::forward<Args>(args)...).template cast<Return>();
|
||||
}
|
||||
};
|
||||
|
||||
value = func_wrapper(func_handle(std::move(func)));
|
||||
value = type_caster_std_function_specializations::func_wrapper<Return, Args...>(
|
||||
type_caster_std_function_specializations::func_handle(std::move(func)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,7 @@ set(PYBIND11_TEST_FILES
|
||||
test_tagbased_polymorphic
|
||||
test_thread
|
||||
test_type_caster_pyobject_ptr
|
||||
test_type_caster_std_function_specializations
|
||||
test_union
|
||||
test_unnamed_namespace_a
|
||||
test_unnamed_namespace_b
|
||||
|
@ -10,6 +10,10 @@ name = "pybind11_tests"
|
||||
version = "0.0.1"
|
||||
dependencies = ["pytest", "pytest-timeout", "numpy", "scipy"]
|
||||
|
||||
[tool.scikit-build]
|
||||
# Hide a warning while we also support CMake < 3.15
|
||||
cmake.version = ">=3.15"
|
||||
|
||||
[tool.scikit-build.cmake.define]
|
||||
PYBIND11_FINDPYTHON = true
|
||||
|
||||
|
46
tests/test_type_caster_std_function_specializations.cpp
Normal file
46
tests/test_type_caster_std_function_specializations.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include "pybind11_tests.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
namespace {
|
||||
|
||||
struct SpecialReturn {
|
||||
int value = 99;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace pybind11 {
|
||||
namespace detail {
|
||||
namespace type_caster_std_function_specializations {
|
||||
|
||||
template <typename... Args>
|
||||
struct func_wrapper<SpecialReturn, Args...> : func_wrapper_base {
|
||||
using func_wrapper_base::func_wrapper_base;
|
||||
SpecialReturn operator()(Args... args) const {
|
||||
gil_scoped_acquire acq;
|
||||
SpecialReturn result;
|
||||
try {
|
||||
result = hfunc.f(std::forward<Args>(args)...).template cast<SpecialReturn>();
|
||||
} catch (error_already_set &) {
|
||||
result.value += 1;
|
||||
}
|
||||
result.value += 100;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace type_caster_std_function_specializations
|
||||
} // namespace detail
|
||||
} // namespace pybind11
|
||||
|
||||
TEST_SUBMODULE(type_caster_std_function_specializations, m) {
|
||||
py::class_<SpecialReturn>(m, "SpecialReturn")
|
||||
.def(py::init<>())
|
||||
.def_readwrite("value", &SpecialReturn::value);
|
||||
m.def("call_callback_with_special_return",
|
||||
[](const std::function<SpecialReturn()> &func) { return func(); });
|
||||
}
|
15
tests/test_type_caster_std_function_specializations.py
Normal file
15
tests/test_type_caster_std_function_specializations.py
Normal file
@ -0,0 +1,15 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pybind11_tests import type_caster_std_function_specializations as m
|
||||
|
||||
|
||||
def test_callback_with_special_return():
|
||||
def return_special():
|
||||
return m.SpecialReturn()
|
||||
|
||||
def raise_exception():
|
||||
raise ValueError("called raise_exception.")
|
||||
|
||||
assert return_special().value == 99
|
||||
assert m.call_callback_with_special_return(return_special).value == 199
|
||||
assert m.call_callback_with_special_return(raise_exception).value == 200
|
@ -2,7 +2,7 @@
|
||||
|
||||
Adds the following targets::
|
||||
|
||||
pybind11::pybind11 - link to headers and pybind11
|
||||
pybind11::pybind11 - link to Python headers and pybind11::headers
|
||||
pybind11::module - Adds module links
|
||||
pybind11::embed - Adds embed links
|
||||
pybind11::lto - Link time optimizations (only if CMAKE_INTERPROCEDURAL_OPTIMIZATION is not set)
|
||||
@ -75,6 +75,32 @@ set_property(
|
||||
APPEND
|
||||
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11)
|
||||
|
||||
# -------------- emscripten requires exceptions enabled -------------
|
||||
# _pybind11_no_exceptions is a private mechanism to disable this addition.
|
||||
# Please open an issue if you need to use it; it will be removed if no one
|
||||
# needs it.
|
||||
if(CMAKE_SYSTEM_NAME MATCHES Emscripten AND NOT _pybind11_no_exceptions)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.13)
|
||||
message(WARNING "CMake 3.13+ is required to build for Emscripten. Some flags will be missing")
|
||||
else()
|
||||
if(_is_config)
|
||||
set(_tmp_config_target pybind11::pybind11_headers)
|
||||
else()
|
||||
set(_tmp_config_target pybind11_headers)
|
||||
endif()
|
||||
|
||||
set_property(
|
||||
TARGET ${_tmp_config_target}
|
||||
APPEND
|
||||
PROPERTY INTERFACE_LINK_OPTIONS -fexceptions)
|
||||
set_property(
|
||||
TARGET ${_tmp_config_target}
|
||||
APPEND
|
||||
PROPERTY INTERFACE_COMPILE_OPTIONS -fexceptions)
|
||||
unset(_tmp_config_target)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --------------------------- link helper ---------------------------
|
||||
|
||||
add_library(pybind11::python_link_helper IMPORTED INTERFACE ${optional_global})
|
||||
@ -329,7 +355,7 @@ function(_pybind11_generate_lto target prefer_thin_lto)
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le" OR CMAKE_SYSTEM_PROCESSOR MATCHES "mips64")
|
||||
# Do nothing
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES emscripten)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES Emscripten)
|
||||
# This compile is very costly when cross-compiling, so set this without checking
|
||||
set(PYBIND11_LTO_CXX_FLAGS "-flto${thin}${cxx_append}")
|
||||
set(PYBIND11_LTO_LINKER_FLAGS "-flto${thin}${linker_append}")
|
||||
|
@ -84,7 +84,7 @@ you can either use the basic targets, or use the FindPython tools:
|
||||
|
||||
# Python method:
|
||||
Python_add_library(MyModule2 src2.cpp)
|
||||
target_link_libraries(MyModule2 pybind11::headers)
|
||||
target_link_libraries(MyModule2 PUBLIC pybind11::headers)
|
||||
set_target_properties(MyModule2 PROPERTIES
|
||||
INTERPROCEDURAL_OPTIMIZATION ON
|
||||
CXX_VISIBILITY_PRESET ON
|
||||
|
Loading…
Reference in New Issue
Block a user