2015-07-05 18:05:44 +00:00
|
|
|
/*
|
2015-10-15 16:13:33 +00:00
|
|
|
pybind11/cast.h: Partial template specializations to cast between
|
2015-07-05 18:05:44 +00:00
|
|
|
C++ and Python types
|
|
|
|
|
2016-04-17 18:21:41 +00:00
|
|
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
2015-07-05 18:05:44 +00:00
|
|
|
|
|
|
|
All rights reserved. Use of this source code is governed by a
|
|
|
|
BSD-style license that can be found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2015-07-11 15:41:48 +00:00
|
|
|
#pragma once
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2021-02-23 02:38:18 +00:00
|
|
|
#include "detail/common.h"
|
2017-08-13 22:35:53 +00:00
|
|
|
#include "detail/descr.h"
|
2024-07-31 21:06:39 +00:00
|
|
|
#include "detail/native_enum_data.h"
|
2021-02-23 02:38:18 +00:00
|
|
|
#include "detail/type_caster_base.h"
|
|
|
|
#include "detail/typeid.h"
|
2022-02-10 20:17:07 +00:00
|
|
|
#include "pytypes.h"
|
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
#include <array>
|
2021-02-23 02:38:18 +00:00
|
|
|
#include <cstring>
|
|
|
|
#include <functional>
|
|
|
|
#include <iosfwd>
|
|
|
|
#include <iterator>
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
2017-03-26 03:51:40 +00:00
|
|
|
#include <tuple>
|
2018-07-17 13:48:51 +00:00
|
|
|
#include <type_traits>
|
2021-02-23 02:38:18 +00:00
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
2022-11-28 15:39:38 +00:00
|
|
|
|
|
|
|
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
2017-07-29 02:03:44 +00:00
|
|
|
|
Adding py::smart_holder (for smart-pointer interoperability). (#2672)
* Adding test_unique_ptr_member (for desired PyCLIF behavior).
See also: https://github.com/pybind/pybind11/issues/2583
Does not build with upstream master or
https://github.com/pybind/pybind11/pull/2047, but builds with
https://github.com/RobotLocomotion/pybind11 and almost runs:
```
Running tests in directory "/usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests":
================================================================================= test session starts =================================================================================
platform linux -- Python 3.8.5, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests, inifile: pytest.ini
collected 2 items
test_unique_ptr_member.py .F [100%]
====================================================================================== FAILURES =======================================================================================
_____________________________________________________________________________ test_pointee_and_ptr_owner ______________________________________________________________________________
def test_pointee_and_ptr_owner():
obj = m.pointee()
assert obj.get_int() == 213
m.ptr_owner(obj)
with pytest.raises(ValueError) as exc_info:
> obj.get_int()
E Failed: DID NOT RAISE <class 'ValueError'>
test_unique_ptr_member.py:17: Failed
============================================================================= 1 failed, 1 passed in 0.06s =============================================================================
```
* unique_ptr or shared_ptr return
* new test_variant_unique_shared with vptr_holder prototype
* moving prototype code to pybind11/vptr_holder.h, adding type_caster specialization to make the bindings involving unique_ptr passing compile, but load and cast implementations are missing
* disabling GitHub Actions on pull_request (for this PR)
* disabling AppVeyor (for this PR)
* TRIGGER_SEGSEV macro, annotations for GET_STACK (vptr::get), GET_INT_STACK (pointee)
* adding test_promotion_of_disowned_to_shared
* Copying tests as-is from xxx_value_ptr_xxx_holder branch.
https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder
Systematically exercising returning and passing unique_ptr<T>, shared_ptr<T>
with unique_ptr, shared_ptr holder.
Observations:
test_holder_unique_ptr:
make_unique_pointee OK
pass_unique_pointee BUILD_FAIL (as documented)
make_shared_pointee Abort free(): double free detected
pass_shared_pointee RuntimeError: Unable to load a custom holder type from a default-holder instance
test_holder_shared_ptr:
make_unique_pointee Segmentation fault (#1138)
pass_unique_pointee BUILD_FAIL (as documented)
make_shared_pointee OK
pass_shared_pointee OK
* Copying tests as-is from xxx_value_ptr_xxx_holder branch.
https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder
Systematically exercising casting between shared_ptr<base>, shared_ptr<derived>.
* Demonstration of Undefined Behavior in handling of shared_ptr holder.
Based on https://godbolt.org/z/4fdjaW by jorgbrown@ (thanks Jorg!).
* Additional demonstration of Undefined Behavior in handling of shared_ptr holder.
* fixing up-down mixup in comment
* Demonstration of Undefined Behavior in handling of polymorphic pointers.
(This demo does NOT involve smart pointers at all, unlike the otherwise similar test_smart_ptr_private_first_base.)
* minor test_private_first_base.cpp simplification (after discovering that this can be wrapped with Boost.Python, using boost::noncopyable)
* pybind11 equivalent of Boost.Python test similar to reproducer under #1333
* Snapshot of WIP, TODO: shared_ptr deleter with on/off switch
* Adding vptr_deleter.
* Adding from/as unique_ptr<T> and unique_ptr<T, D>.
* Adding from_shared_ptr. Some polishing.
* New tests/core/smart_holder_poc_test.cpp, using Catch2.
* Adding in vptr_deleter_guard_flag.
* Improved labeling of TEST_CASEs.
* Shuffling existing TEST_CASEs into systematic matrix.
* Implementing all [S]uccess tests.
* Implementing all [E]xception tests.
* Testing of exceptions not covered by the from-as matrix.
* Adding top-level comment.
* Converting from methods to factory functions (no functional change).
* Removing obsolete and very incomplete test (replaced by Catch2-based test).
* Removing stray file.
* Adding type_caster_bare_interface_demo.
* Adding shared_ptr<mpty>, shared_ptr<mpty const> casters.
* Adding unique_ptr<mpty>, unique_ptr<mpty const> casters.
* Pure copy of `class class_` implementation in pybind11.h (master commit 98f1bbb8004f654ba9e26717bdf5912fb899b05a).
* classh.h: renaming of class_ to classh + namespace; forking test_classh_wip from test_type_caster_bare_interface_demo.
* Hard-coding smart_holder into classh.
* Adding mpty::mtxt string member.
* Adding isinstance<mpty> in type_caster::load functions.
* Adding rvalue_ref, renaming const_value_ref to lvalue_ref & removing const.
* Retrieving smart_holder pointer in type_caster<mpty>::load, and using it cast_op operators.
* Factoring out smart_holder_type_caster_load.
* Retrieving smart_holder pointer in type_caster<std::shared_ptr<mpty[ const]>>::load, and using it cast_op operators.
* Improved error messaging: Cannot disown nullptr (as_unique_ptr).
* Retrieving smart_holder pointer in type_caster<std::unique_ptr<mpty[ const]>>::load, and using it cast_op operators.
* Pure `clang-format --style=file -i` change.
* Pure `clang-format --style=file -i` change, with two `clang-format off` directives.
* Fixing oversight (discovered by flake8).
* flake8 cleanup
* Systematically setting mtxt for all rtrn_mpty_* functions (preparation, the values are not actually used yet).
* static cast handle for rtrn_cptr works by simply dropping in code from type_caster_base (marked with comments).
* static cast handle for rtrn_cref works by simply dropping in code from type_caster_base (marked with comments). rtrn_mref and rtrn_mptr work via const_cast (to add const).
* static cast handle for rtrn_valu works by simply dropping in code from type_caster_base (marked with comments). rtrn_rref raises a RuntimeError, to be investigated.
* Copying type_caster_generic::cast into type_caster<mpty> as-is (preparation for handling smart pointers).
* Pure clang-format change (applied to original type_caster_generic::cast).
* Adding comment re potential use_count data race.
* static handle cast implementations for rtrn_shmp, rtrn_shcp.
* Adding MISSING comments in operator std::unique_ptr<mpty[ const]>.
* static handle cast implementations for rtrn_uqmp, rtrn_uqcp.
* Bug fix: vptr_deleter_armed_flag_ptr has to live on the heap.
See new bullet point in comment section near the top.
The variable was also renamed to reflect its function more accurately.
* Fixing bugs discovered by ASAN. The code is now ASAN, MSAN, UBSAN clean.
* Making test_type_caster_bare_interface_demo.cpp slightly more realistic, ASAN, MSAN, UBSAN clean.
* Calling deregister_instance after disowning via unique_ptr.
* Removing enable_shared_from_this stub, simplifying existing code, clang-format.
Open question, with respect to the original code:
https://github.com/pybind/pybind11/blob/76a160070b369f8d82b945c97924227e8b835c94/include/pybind11/pybind11.h#L1510
To me it looks like the exact situation marked as `std::shared_ptr<Good> gp1 = not_so_good.getptr();` here: https://en.cppreference.com/w/cpp/memory/enable_shared_from_this
The comment there is: `// undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17)`
Does the existing code have UB pre C++17?
I'll leave handling of enable_shared_from_this for later, as the need arises.
* Cosmetical change around helper functions.
* Using type_caster_base<mpty>::src_and_type directly, removing copy. Also renaming one cast to cast_const_raw_ptr, for clarity.
* Fixing clang-format oversight.
* Using factored-out make_constructor (PR #2798), removing duplicate code.
* Inserting additional assert to ensure a returned unique_ptr is always a new Python instance.
* Adding minor comment (change to internals needed to distinguish uninitialized/disowned in error message).
* Factoring out find_existing_python_instance().
* Moving factored-out make_constructor to test_classh_wip.cpp, restoring previous version of cast.h. This is currently the most practical approach. See PR #2798 for background.
* Copying classh type_casters from test_classh_wip.cpp UNMODIFIED, as a baseline for generalizing the code.
* Using pybind11/detail/classh_type_casters.h from test_classh_wip.cpp.
* Adding & using PYBIND11_CLASSH_TYPE_CASTERS define.
* Adding test_classh_inheritance, currently failing (passes with class_).
* Removing .clang-format before git rebase master (where the file was added).
* Bringing back .clang-format, the previous rm was a bad idea.
* Folding in modified_type_caster_generic_load_impl, just enough to pass test_class_wip. test_classh_inheritance is still failing, but with a different error: [RuntimeError: Incompatible type (as_raw_ptr_unowned).]
* Minimal changes needed to pass test_classh_inheritance.
* First pass adjusting try_implicit_casts and try_load_foreign_module_local to capture loaded_v_h, but untested and guarded with pybind11_failure("Untested"). This was done mainly to determine general feasibility. Note the TODO in pybind11.h, where type_caster_generic::local_load is currently hard-coded. test_classh_wip and test_classh_inheritance still pass, as before.
* Decoupling generic_type from type_caster_generic.
* Changes and tests covering classh_type_casters try_implicit_casts.
* Minimal test covering classh_type_casters load_impl Case 2b.
* Removing stray isinstance<T>(src): it interferes with the py::module_local feature. Adding missing #includes.
* Tests for classh py::module_local() feature.
* Pure renaming of function names in test_classh_inheritance, similar to the systematic approach used in test_class_wip. NO functional changes.
* Pure renaming of function and variable names, for better generalization when convoluting with inheritance. NO functional changes.
* Adopting systematic naming scheme from test_classh_wip. NO functional changes.
* Moving const after type name, for functions that cover a systematic scheme. NO functional changes.
* Adding smart_holder_type_caster_load::loaded_as_shared_ptr, currently bypassing smart_holder shared_ptr tracking completely, but the tests pass and are sanitizer clean.
* Removing rtti_held from smart_holder. See updated comment.
* Cleaning up loaded_as_raw_ptr_unowned, loaded_as_shared_ptr.
* Factoring out convert_type and folding into loaded_as_unique_ptr.
* Folding convert_type into lvalue_ref and rvalue_ref paths. Some smart_holder_type_caster_load cleanup.
* Using unique_ptr in local_load to replace static variable. Also adding local_load_safety_guard.
* Converting test_unique_ptr_member to using classh: fully working, ASAN, MSAN, UBSAN clean.
* Removing debugging comments (GET_STACK, GET_INT_STACK). cast.h is identical to current master again, pybind11.h only has the generic_type::initialize(..., &type_caster_generic::local_load) change.
* Purging obsolete pybind11/vptr_holder.h and associated test.
* Moving several tests to github.com/rwgk/rwgk_tbx/tree/main/pybind11_tests
https://github.com/rwgk/rwgk_tbx/commit/a2c2f88174a30f5de80d7d26e0f77c7b60f5fb85
These tests are from experimenting, and for demonstrating UB in pybind11 multiple inheritance handling ("first_base"), to be fixed later.
* Adding py::smart_holder support to py::class_, purging py::classh completely.
* Renaming files in include directory, creating pybind11/smart_holder.h.
* Renaming all "classh" to "smart_holder" in pybind11/detail/smart_holder_type_casters.h.
The user-facing macro is now PYBIND11_SMART_HOLDER_TYPE_CASTERS.
* Systematically renaming tests to use "class_sh" in the name.
* Renaming test_type_caster_bare_interface_demo to test_type_caster_bare_interface.
* Renaming new tests/core subdirectory to tests/pure_cpp.
* Adding new tests to CMake config, resetting CI config.
* Changing CMake file so that test_class_sh_module_local.py actually runs.
* clang-tidy fixes.
* 32-bit compatibility.
* Reusing type_caster_base make_copy_constructor, make_move_constructor with a trick.
* CMake COMPARE NATURAL is not available with older versions.
* Adding copyright notices to new header files.
* Explicitly define copy/move constructors/assignments.
* Adding new header files to tests/extra_python_package/test_files.py.
* Adding tests/pure_cpp/CMakeLists.txt.
* Making use of the new find_existing_python_instance() function factored out with PR #2822.
* Moving define PYBIND11_SMART_HOLDER_TYPE_CASTERS(T) down in the file. NO functional changes. Preparation for follow-up work (to keep that diff smaller).
* Reintroducing py::classh, this time as a simple alias for py::class_<U, py::smart_holder>.
* Replacing detail::is_smart_holder<H> in cast.h with detail::is_smart_holder_type_caster<T>.
Moving get_local_load_function_ptr, init_instance_for_type to smart_holder_type_caster_class_hooks.
Expanding static_assert in py::type::handle_of<> to accommodate smart_holder_type_casters.
* Fixing oversight.
* Adding classu alias for class_<U, std::unique_ptr<U>>.
* Giving up on idea to use legacy init_instance only if is_base_of<type_caster_generic, type_caster<T>. There are use cases in the wild that define both a custom type_caster and class_.
* Removing test_type_caster_bare_interface, which was moved to the separate PR #2834.
* Moving up is_smart_holder_type_caster, to also use in cast_is_temporary_value_reference.
* Adding smart_holder_type_casters for unique_ptr with custom deleter. SEVERE CODE DUPLICATION. This commit is to establish a baseline for consolidating the unique_ptr code.
* Unification of unique_ptr, unique_ptr_with_deleter code in smart_holder_poc.h. Leads to more fitting error messages. Enables use of unique_ptr<T, D> smart_holder_type_casters also for unique_ptr<T>.
* Copying files as-is from branch test_unique_ptr_member (PR #2672).
* Adding comment, simplifying naming, cmake addition.
* Introducing PYBIND11_USE_SMART_HOLDER_AS_DEFAULT macro (tested only undefined; there are many errors with the macro defined).
* Removing test_type_caster_bare_interface, which was moved to the separate PR #2834.
* Fixing oversight introduced with commit 95425f13d6c14fcb6ee479b62b602dc8a605ec49.
* Setting record.default_holder correctly for PYBIND11_USE_SMART_HOLDER_AS_DEFAULT.
With this test_class.cpp builds and even mostly runs, except
`test_multiple_instances_with_same_pointer`, which segfaults because it is
using a `unique_ptr` holder but `smart_holder` `type_caster`.
Also adding `static_assert`s to generate build errors for such situations,
but guarding with `#if 0` to first pivot to test_factory_constructors.cpp.
* Fixing up cast.h and smart_holder.h after rebase.
* Removing detail/smart_holder_type_casters.h in separate commit.
* Commenting out const in def_buffer(... const). With this, test_buffers builds and runs with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT. Explanation why the const needs to be removed, or fix elsewhere, is still needed, but left for later.
* Adding test_class_sh_factory_constructors, reproducing test_factory_constructors failure. Using py::class_ in this commit, to be changed to py::classh for debugging.
* Removing include/pybind11/detail/smart_holder_type_casters.h from CMakeLists.txt, test_files.py (since it does not exist in this branch).
* Adding // DANGER ZONE reminders.
* Converting as many py::class_ to py::classh as possible, not breaking tests.
* Adding initimpl::construct() overloads, resulting in test_class_sh_factory_constructors feature parity for py::class_ and py::classh.
* Adding enable_if !is_smart_holder_type_caster to existing initimpl::construct(). With this test_factory_constructors.cpp builds with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT.
* Disabling shared_ptr&, shared_ptr* tests when building with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT for now, pending work on smart_holder_type_caster<shared_ptr>.
* Factoring out struct and class definitions into anonymous namespace. Preparation for building with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT.
* Simplifying from_unique_ptr(): typename D = std::default_delete<T> is not needed. Factoring out is_std_default_delete<T>() for consistentcy between ensure_compatible_rtti_uqp_del() and from_unique_ptr().
* Introducing PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS. Using it in test_smart_ptr.cpp. With this test_smart_ptr builds with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT and all but one test run successfully.
* Introducing 1. type_caster_for_class_, used in PYBIND11_MAKE_OPAQUE, and 2. default_holder_type, used in stl_bind.h.
* Using __VA_ARGS__ in PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS.
* Replacing condense_for_macro with much simpler approach.
* Softening static_assert, to only check specifically that smart_holder is not mixed with type_caster_base, and unique_ptr/shared_ptr holders are not mixed with smart_holder_type_casters.
* Adding PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS in test_class.cpp (with this all but one test succeed with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT).
* Adding remaining PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS. static_assert for "necessary conditions" for both types of default holder, static_assert for "strict conditions" guarded by new PYBIND11_STRICT_ASSERTS_CLASS_HOLDER_VS_TYPE_CASTER_MIX. All tests build & run as before with unique_ptr as the default holder, all tests build for smart_holder as the default holder, even with the strict static_assert.
* Introducing check_is_smart_holder_type_caster() function for runtime check, and reinterpreting record.default_holder as "uses_unique_ptr_holder". With this test_smart_ptr succeeds. (All 42 tests build, 35 tests succeed, 5 run but have some failures, 2 segfault.)
* Bug fix: Adding have_value() to smart_holder_type_caster_load. With this test_builtin_casters succeeds. (All 42 tests build, 36 tests succeed, 5 run but have some failures, 1 segfault.)
* Adding unowned_void_ptr_from_direct_conversion to modified_type_caster_generic_load_impl. This fixes the last remaining segfault (test_numpy_dtypes). New stats for all tests combined: 12 failed, 458 passed.
* Adding "Lazy allocation for unallocated values" (for old-style __init__) into load_value_and_holder. Deferring destruction of disowned holder until clear_instance, to remain inspectable for "uninitialized" or "disowned" detection. New stats for all tests combined: 5 failed, 465 passed.
* Changing std::shared_ptr pointer/reference to const pointer/reference. New stats for all tests combined: 4 failed, 466 passed.
* Adding return_value_policy::move to permissible policies for unique_ptr returns. New stats for all tests combined: 3 failed, 467 passed.
* Overlooked flake8 fixes.
* Manipulating failing ConstructorStats test to pass, to be able to run all tests with ASAN.
This version of the code is ASAN clean with unique_ptr or smart_holder as the default.
This change needs to be reverted after adopting the existing move-only-if-refcount-is-1
logic used by type_caster_base.
* Adding copy constructor and move constructor tracking to atyp. Preparation for a follow-up change in smart_holder_type_caster, to make this test sensitive to the changing behavior.
[skip ci]
* Removing `operator T&&() &&` from smart_holder_type_caster, for compatibility with the behavior of type_caster_base. Enables reverting 2 of 3 test manipulations applied under commit 249df7cbdb09817fed0ddf80f01ba5af12466820. The manipulation in test_factory_constructors.py is NOT reverted in this commit.
[skip ci]
* Fixing unfortunate editing mishap. This reverts the last remaining test manipulation in commit 249df7cbdb09817fed0ddf80f01ba5af12466820 and makes all existing unit tests pass with smart_holder as default holder.
* GitHub CI clang-tidy fixes.
* Adding messages to terse `static_assert`s, for pre-C++17 compatibility.
* Using @pytest.mark.parametrize to run each assert separately (to see all errors, not just the first).
* Systematically removing _atyp from function names, to make the test code simpler.
* Using re.match to accommodate variable number of intermediate MvCtor.
* Also removing `operator T()` from smart_holder_type_caster, to fix gcc compilation errors. The only loss is pass_rref in test_class_sh_basic.
* Systematically replacing `detail::enable_if_t<...smart_holder...>` with `typename std::enable_if<...smart_holder...>::type`. Attempt to work around MSVC 2015 issues, to be tested via GitHub CI. The idea for this change originates from this comment: https://github.com/pybind/pybind11/issues/1616#issuecomment-444536813
* Importing re before pytest after observing a PyPy CI flake when importing pytest first.
* Copying MSVC 2015 compatibility change from branch pr2672_use_smart_holder_as_default.
* Introducing is_smart_holder_type_caster_base_tag, to keep smart_holder code more disconnected.
* Working around MSVC 2015 bug.
* Expanding comment for MSVC 2015 workaround.
* Systematically changing std::enable_if back to detail::enable_if_t, effectively reverting commit 5d4b6890a337ae1bbaec4091f4195606f89a3b06.
* Removing unused smart_holder_type_caster_load::loaded_as_rvalue_ref (it was an oversight that it was not removed with commit 23036a45eb4731a06b488ec1fdf83bca677b7f67).
* Removing py::classu, because it does not seem useful enough.
* Reverting commit 63495313066119dcf7510c2ae8b468b46c12ef8f by un-commenting `const` in `def_buffer(...)`. To make this possible, `operator T const&` and `operator T const*` in `smart_holder_type_caster` need to be marked as `const` member functions.
* Adding construct() overloads for constructing smart_holder from alias unique_ptr, shared_ptr returns.
* Adding test_class_sh_factory_constructors.cpp to tests/CMakeLists.txt (fixes oversight, this should have been added long before).
* Compatibility with old clang versions (clang 3.6, 3.7 C++11).
* Cleaning up changes to existing unit tests.
* Systematically adding SMART_HOLDER_WIP tag. Removing minor UNTESTED tags (only the throw are not actually exercised, investing time there has a high cost but very little benefit).
* Splitting out smart_holder_type_casters again, into new detail/smart_holder_type_casters_inline_include.h.
* Splitting out smart_holder_init_inline_include.h.
* Adding additional new include files to CMakeLists.txt, tests/extra_python_package/test_files.py.
* clang-format cleanup of most smart_holder code.
* Adding source code comments in response to review.
* Simple micro-benchmark ("ubench") comparing runtime performance for several holders.
Tested using github.com/rwgk/pybind11_scons and Google-internal build system.
Sorry, no cmake support at the moment.
First results: https://docs.google.com/spreadsheets/d/1InapCYws2Gt-stmFf_Bwl33eOMo3aLE_gc9adveY7RU/edit#gid=0
* Breaking out number_bucket.h, adding hook for also collecting performance data for PyCLIF.
* Accounting for ubench in MANIFEST.in (simply prune, for now).
* Smarter determination of call_repetitions.
[skip ci]
* Also scaling performance data to PyCLIF.
[skip ci]
* Adding ubench/python/number_bucket.clif here for general visibility.
* Fix after rebase
* Merging detail/smart_holder_init_inline_include.h into detail/init.h.
* Renaming detail/is_smart_holder_type_caster.h -> detail/smart_holder_sfinae_hooks_only.h.
* Renaming is_smart_holder_type_caster -> type_uses_smart_holder_type_caster for clarity.
* Renaming type_caster_type_is_smart_holder_type_caster -> wrapped_type_uses_smart_holder_type_caster for clarity.
* Renaming is_smart_holder_type_caster_base_tag -> smart_holder_type_caster_base_tag for simplicity.
* Adding copyright notices and minor colateral cleanup.
* iwyu cleanup (comprehensive only for cast.h and smart_holder*.h files).
* Fixing `git rebase master` accident.
* Moving large `pragma warning` block from pybind11.h to detail/common.h.
* Fixing another `git rebase master` accident.
2021-02-24 05:50:42 +00:00
|
|
|
template <typename type, typename SFINAE = void>
|
2024-07-31 13:17:31 +00:00
|
|
|
class type_caster : public type_caster_base<type> {};
|
Adding py::smart_holder (for smart-pointer interoperability). (#2672)
* Adding test_unique_ptr_member (for desired PyCLIF behavior).
See also: https://github.com/pybind/pybind11/issues/2583
Does not build with upstream master or
https://github.com/pybind/pybind11/pull/2047, but builds with
https://github.com/RobotLocomotion/pybind11 and almost runs:
```
Running tests in directory "/usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests":
================================================================================= test session starts =================================================================================
platform linux -- Python 3.8.5, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests, inifile: pytest.ini
collected 2 items
test_unique_ptr_member.py .F [100%]
====================================================================================== FAILURES =======================================================================================
_____________________________________________________________________________ test_pointee_and_ptr_owner ______________________________________________________________________________
def test_pointee_and_ptr_owner():
obj = m.pointee()
assert obj.get_int() == 213
m.ptr_owner(obj)
with pytest.raises(ValueError) as exc_info:
> obj.get_int()
E Failed: DID NOT RAISE <class 'ValueError'>
test_unique_ptr_member.py:17: Failed
============================================================================= 1 failed, 1 passed in 0.06s =============================================================================
```
* unique_ptr or shared_ptr return
* new test_variant_unique_shared with vptr_holder prototype
* moving prototype code to pybind11/vptr_holder.h, adding type_caster specialization to make the bindings involving unique_ptr passing compile, but load and cast implementations are missing
* disabling GitHub Actions on pull_request (for this PR)
* disabling AppVeyor (for this PR)
* TRIGGER_SEGSEV macro, annotations for GET_STACK (vptr::get), GET_INT_STACK (pointee)
* adding test_promotion_of_disowned_to_shared
* Copying tests as-is from xxx_value_ptr_xxx_holder branch.
https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder
Systematically exercising returning and passing unique_ptr<T>, shared_ptr<T>
with unique_ptr, shared_ptr holder.
Observations:
test_holder_unique_ptr:
make_unique_pointee OK
pass_unique_pointee BUILD_FAIL (as documented)
make_shared_pointee Abort free(): double free detected
pass_shared_pointee RuntimeError: Unable to load a custom holder type from a default-holder instance
test_holder_shared_ptr:
make_unique_pointee Segmentation fault (#1138)
pass_unique_pointee BUILD_FAIL (as documented)
make_shared_pointee OK
pass_shared_pointee OK
* Copying tests as-is from xxx_value_ptr_xxx_holder branch.
https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder
Systematically exercising casting between shared_ptr<base>, shared_ptr<derived>.
* Demonstration of Undefined Behavior in handling of shared_ptr holder.
Based on https://godbolt.org/z/4fdjaW by jorgbrown@ (thanks Jorg!).
* Additional demonstration of Undefined Behavior in handling of shared_ptr holder.
* fixing up-down mixup in comment
* Demonstration of Undefined Behavior in handling of polymorphic pointers.
(This demo does NOT involve smart pointers at all, unlike the otherwise similar test_smart_ptr_private_first_base.)
* minor test_private_first_base.cpp simplification (after discovering that this can be wrapped with Boost.Python, using boost::noncopyable)
* pybind11 equivalent of Boost.Python test similar to reproducer under #1333
* Snapshot of WIP, TODO: shared_ptr deleter with on/off switch
* Adding vptr_deleter.
* Adding from/as unique_ptr<T> and unique_ptr<T, D>.
* Adding from_shared_ptr. Some polishing.
* New tests/core/smart_holder_poc_test.cpp, using Catch2.
* Adding in vptr_deleter_guard_flag.
* Improved labeling of TEST_CASEs.
* Shuffling existing TEST_CASEs into systematic matrix.
* Implementing all [S]uccess tests.
* Implementing all [E]xception tests.
* Testing of exceptions not covered by the from-as matrix.
* Adding top-level comment.
* Converting from methods to factory functions (no functional change).
* Removing obsolete and very incomplete test (replaced by Catch2-based test).
* Removing stray file.
* Adding type_caster_bare_interface_demo.
* Adding shared_ptr<mpty>, shared_ptr<mpty const> casters.
* Adding unique_ptr<mpty>, unique_ptr<mpty const> casters.
* Pure copy of `class class_` implementation in pybind11.h (master commit 98f1bbb8004f654ba9e26717bdf5912fb899b05a).
* classh.h: renaming of class_ to classh + namespace; forking test_classh_wip from test_type_caster_bare_interface_demo.
* Hard-coding smart_holder into classh.
* Adding mpty::mtxt string member.
* Adding isinstance<mpty> in type_caster::load functions.
* Adding rvalue_ref, renaming const_value_ref to lvalue_ref & removing const.
* Retrieving smart_holder pointer in type_caster<mpty>::load, and using it cast_op operators.
* Factoring out smart_holder_type_caster_load.
* Retrieving smart_holder pointer in type_caster<std::shared_ptr<mpty[ const]>>::load, and using it cast_op operators.
* Improved error messaging: Cannot disown nullptr (as_unique_ptr).
* Retrieving smart_holder pointer in type_caster<std::unique_ptr<mpty[ const]>>::load, and using it cast_op operators.
* Pure `clang-format --style=file -i` change.
* Pure `clang-format --style=file -i` change, with two `clang-format off` directives.
* Fixing oversight (discovered by flake8).
* flake8 cleanup
* Systematically setting mtxt for all rtrn_mpty_* functions (preparation, the values are not actually used yet).
* static cast handle for rtrn_cptr works by simply dropping in code from type_caster_base (marked with comments).
* static cast handle for rtrn_cref works by simply dropping in code from type_caster_base (marked with comments). rtrn_mref and rtrn_mptr work via const_cast (to add const).
* static cast handle for rtrn_valu works by simply dropping in code from type_caster_base (marked with comments). rtrn_rref raises a RuntimeError, to be investigated.
* Copying type_caster_generic::cast into type_caster<mpty> as-is (preparation for handling smart pointers).
* Pure clang-format change (applied to original type_caster_generic::cast).
* Adding comment re potential use_count data race.
* static handle cast implementations for rtrn_shmp, rtrn_shcp.
* Adding MISSING comments in operator std::unique_ptr<mpty[ const]>.
* static handle cast implementations for rtrn_uqmp, rtrn_uqcp.
* Bug fix: vptr_deleter_armed_flag_ptr has to live on the heap.
See new bullet point in comment section near the top.
The variable was also renamed to reflect its function more accurately.
* Fixing bugs discovered by ASAN. The code is now ASAN, MSAN, UBSAN clean.
* Making test_type_caster_bare_interface_demo.cpp slightly more realistic, ASAN, MSAN, UBSAN clean.
* Calling deregister_instance after disowning via unique_ptr.
* Removing enable_shared_from_this stub, simplifying existing code, clang-format.
Open question, with respect to the original code:
https://github.com/pybind/pybind11/blob/76a160070b369f8d82b945c97924227e8b835c94/include/pybind11/pybind11.h#L1510
To me it looks like the exact situation marked as `std::shared_ptr<Good> gp1 = not_so_good.getptr();` here: https://en.cppreference.com/w/cpp/memory/enable_shared_from_this
The comment there is: `// undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17)`
Does the existing code have UB pre C++17?
I'll leave handling of enable_shared_from_this for later, as the need arises.
* Cosmetical change around helper functions.
* Using type_caster_base<mpty>::src_and_type directly, removing copy. Also renaming one cast to cast_const_raw_ptr, for clarity.
* Fixing clang-format oversight.
* Using factored-out make_constructor (PR #2798), removing duplicate code.
* Inserting additional assert to ensure a returned unique_ptr is always a new Python instance.
* Adding minor comment (change to internals needed to distinguish uninitialized/disowned in error message).
* Factoring out find_existing_python_instance().
* Moving factored-out make_constructor to test_classh_wip.cpp, restoring previous version of cast.h. This is currently the most practical approach. See PR #2798 for background.
* Copying classh type_casters from test_classh_wip.cpp UNMODIFIED, as a baseline for generalizing the code.
* Using pybind11/detail/classh_type_casters.h from test_classh_wip.cpp.
* Adding & using PYBIND11_CLASSH_TYPE_CASTERS define.
* Adding test_classh_inheritance, currently failing (passes with class_).
* Removing .clang-format before git rebase master (where the file was added).
* Bringing back .clang-format, the previous rm was a bad idea.
* Folding in modified_type_caster_generic_load_impl, just enough to pass test_class_wip. test_classh_inheritance is still failing, but with a different error: [RuntimeError: Incompatible type (as_raw_ptr_unowned).]
* Minimal changes needed to pass test_classh_inheritance.
* First pass adjusting try_implicit_casts and try_load_foreign_module_local to capture loaded_v_h, but untested and guarded with pybind11_failure("Untested"). This was done mainly to determine general feasibility. Note the TODO in pybind11.h, where type_caster_generic::local_load is currently hard-coded. test_classh_wip and test_classh_inheritance still pass, as before.
* Decoupling generic_type from type_caster_generic.
* Changes and tests covering classh_type_casters try_implicit_casts.
* Minimal test covering classh_type_casters load_impl Case 2b.
* Removing stray isinstance<T>(src): it interferes with the py::module_local feature. Adding missing #includes.
* Tests for classh py::module_local() feature.
* Pure renaming of function names in test_classh_inheritance, similar to the systematic approach used in test_class_wip. NO functional changes.
* Pure renaming of function and variable names, for better generalization when convoluting with inheritance. NO functional changes.
* Adopting systematic naming scheme from test_classh_wip. NO functional changes.
* Moving const after type name, for functions that cover a systematic scheme. NO functional changes.
* Adding smart_holder_type_caster_load::loaded_as_shared_ptr, currently bypassing smart_holder shared_ptr tracking completely, but the tests pass and are sanitizer clean.
* Removing rtti_held from smart_holder. See updated comment.
* Cleaning up loaded_as_raw_ptr_unowned, loaded_as_shared_ptr.
* Factoring out convert_type and folding into loaded_as_unique_ptr.
* Folding convert_type into lvalue_ref and rvalue_ref paths. Some smart_holder_type_caster_load cleanup.
* Using unique_ptr in local_load to replace static variable. Also adding local_load_safety_guard.
* Converting test_unique_ptr_member to using classh: fully working, ASAN, MSAN, UBSAN clean.
* Removing debugging comments (GET_STACK, GET_INT_STACK). cast.h is identical to current master again, pybind11.h only has the generic_type::initialize(..., &type_caster_generic::local_load) change.
* Purging obsolete pybind11/vptr_holder.h and associated test.
* Moving several tests to github.com/rwgk/rwgk_tbx/tree/main/pybind11_tests
https://github.com/rwgk/rwgk_tbx/commit/a2c2f88174a30f5de80d7d26e0f77c7b60f5fb85
These tests are from experimenting, and for demonstrating UB in pybind11 multiple inheritance handling ("first_base"), to be fixed later.
* Adding py::smart_holder support to py::class_, purging py::classh completely.
* Renaming files in include directory, creating pybind11/smart_holder.h.
* Renaming all "classh" to "smart_holder" in pybind11/detail/smart_holder_type_casters.h.
The user-facing macro is now PYBIND11_SMART_HOLDER_TYPE_CASTERS.
* Systematically renaming tests to use "class_sh" in the name.
* Renaming test_type_caster_bare_interface_demo to test_type_caster_bare_interface.
* Renaming new tests/core subdirectory to tests/pure_cpp.
* Adding new tests to CMake config, resetting CI config.
* Changing CMake file so that test_class_sh_module_local.py actually runs.
* clang-tidy fixes.
* 32-bit compatibility.
* Reusing type_caster_base make_copy_constructor, make_move_constructor with a trick.
* CMake COMPARE NATURAL is not available with older versions.
* Adding copyright notices to new header files.
* Explicitly define copy/move constructors/assignments.
* Adding new header files to tests/extra_python_package/test_files.py.
* Adding tests/pure_cpp/CMakeLists.txt.
* Making use of the new find_existing_python_instance() function factored out with PR #2822.
* Moving define PYBIND11_SMART_HOLDER_TYPE_CASTERS(T) down in the file. NO functional changes. Preparation for follow-up work (to keep that diff smaller).
* Reintroducing py::classh, this time as a simple alias for py::class_<U, py::smart_holder>.
* Replacing detail::is_smart_holder<H> in cast.h with detail::is_smart_holder_type_caster<T>.
Moving get_local_load_function_ptr, init_instance_for_type to smart_holder_type_caster_class_hooks.
Expanding static_assert in py::type::handle_of<> to accommodate smart_holder_type_casters.
* Fixing oversight.
* Adding classu alias for class_<U, std::unique_ptr<U>>.
* Giving up on idea to use legacy init_instance only if is_base_of<type_caster_generic, type_caster<T>. There are use cases in the wild that define both a custom type_caster and class_.
* Removing test_type_caster_bare_interface, which was moved to the separate PR #2834.
* Moving up is_smart_holder_type_caster, to also use in cast_is_temporary_value_reference.
* Adding smart_holder_type_casters for unique_ptr with custom deleter. SEVERE CODE DUPLICATION. This commit is to establish a baseline for consolidating the unique_ptr code.
* Unification of unique_ptr, unique_ptr_with_deleter code in smart_holder_poc.h. Leads to more fitting error messages. Enables use of unique_ptr<T, D> smart_holder_type_casters also for unique_ptr<T>.
* Copying files as-is from branch test_unique_ptr_member (PR #2672).
* Adding comment, simplifying naming, cmake addition.
* Introducing PYBIND11_USE_SMART_HOLDER_AS_DEFAULT macro (tested only undefined; there are many errors with the macro defined).
* Removing test_type_caster_bare_interface, which was moved to the separate PR #2834.
* Fixing oversight introduced with commit 95425f13d6c14fcb6ee479b62b602dc8a605ec49.
* Setting record.default_holder correctly for PYBIND11_USE_SMART_HOLDER_AS_DEFAULT.
With this test_class.cpp builds and even mostly runs, except
`test_multiple_instances_with_same_pointer`, which segfaults because it is
using a `unique_ptr` holder but `smart_holder` `type_caster`.
Also adding `static_assert`s to generate build errors for such situations,
but guarding with `#if 0` to first pivot to test_factory_constructors.cpp.
* Fixing up cast.h and smart_holder.h after rebase.
* Removing detail/smart_holder_type_casters.h in separate commit.
* Commenting out const in def_buffer(... const). With this, test_buffers builds and runs with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT. Explanation why the const needs to be removed, or fix elsewhere, is still needed, but left for later.
* Adding test_class_sh_factory_constructors, reproducing test_factory_constructors failure. Using py::class_ in this commit, to be changed to py::classh for debugging.
* Removing include/pybind11/detail/smart_holder_type_casters.h from CMakeLists.txt, test_files.py (since it does not exist in this branch).
* Adding // DANGER ZONE reminders.
* Converting as many py::class_ to py::classh as possible, not breaking tests.
* Adding initimpl::construct() overloads, resulting in test_class_sh_factory_constructors feature parity for py::class_ and py::classh.
* Adding enable_if !is_smart_holder_type_caster to existing initimpl::construct(). With this test_factory_constructors.cpp builds with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT.
* Disabling shared_ptr&, shared_ptr* tests when building with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT for now, pending work on smart_holder_type_caster<shared_ptr>.
* Factoring out struct and class definitions into anonymous namespace. Preparation for building with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT.
* Simplifying from_unique_ptr(): typename D = std::default_delete<T> is not needed. Factoring out is_std_default_delete<T>() for consistentcy between ensure_compatible_rtti_uqp_del() and from_unique_ptr().
* Introducing PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS. Using it in test_smart_ptr.cpp. With this test_smart_ptr builds with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT and all but one test run successfully.
* Introducing 1. type_caster_for_class_, used in PYBIND11_MAKE_OPAQUE, and 2. default_holder_type, used in stl_bind.h.
* Using __VA_ARGS__ in PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS.
* Replacing condense_for_macro with much simpler approach.
* Softening static_assert, to only check specifically that smart_holder is not mixed with type_caster_base, and unique_ptr/shared_ptr holders are not mixed with smart_holder_type_casters.
* Adding PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS in test_class.cpp (with this all but one test succeed with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT).
* Adding remaining PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS. static_assert for "necessary conditions" for both types of default holder, static_assert for "strict conditions" guarded by new PYBIND11_STRICT_ASSERTS_CLASS_HOLDER_VS_TYPE_CASTER_MIX. All tests build & run as before with unique_ptr as the default holder, all tests build for smart_holder as the default holder, even with the strict static_assert.
* Introducing check_is_smart_holder_type_caster() function for runtime check, and reinterpreting record.default_holder as "uses_unique_ptr_holder". With this test_smart_ptr succeeds. (All 42 tests build, 35 tests succeed, 5 run but have some failures, 2 segfault.)
* Bug fix: Adding have_value() to smart_holder_type_caster_load. With this test_builtin_casters succeeds. (All 42 tests build, 36 tests succeed, 5 run but have some failures, 1 segfault.)
* Adding unowned_void_ptr_from_direct_conversion to modified_type_caster_generic_load_impl. This fixes the last remaining segfault (test_numpy_dtypes). New stats for all tests combined: 12 failed, 458 passed.
* Adding "Lazy allocation for unallocated values" (for old-style __init__) into load_value_and_holder. Deferring destruction of disowned holder until clear_instance, to remain inspectable for "uninitialized" or "disowned" detection. New stats for all tests combined: 5 failed, 465 passed.
* Changing std::shared_ptr pointer/reference to const pointer/reference. New stats for all tests combined: 4 failed, 466 passed.
* Adding return_value_policy::move to permissible policies for unique_ptr returns. New stats for all tests combined: 3 failed, 467 passed.
* Overlooked flake8 fixes.
* Manipulating failing ConstructorStats test to pass, to be able to run all tests with ASAN.
This version of the code is ASAN clean with unique_ptr or smart_holder as the default.
This change needs to be reverted after adopting the existing move-only-if-refcount-is-1
logic used by type_caster_base.
* Adding copy constructor and move constructor tracking to atyp. Preparation for a follow-up change in smart_holder_type_caster, to make this test sensitive to the changing behavior.
[skip ci]
* Removing `operator T&&() &&` from smart_holder_type_caster, for compatibility with the behavior of type_caster_base. Enables reverting 2 of 3 test manipulations applied under commit 249df7cbdb09817fed0ddf80f01ba5af12466820. The manipulation in test_factory_constructors.py is NOT reverted in this commit.
[skip ci]
* Fixing unfortunate editing mishap. This reverts the last remaining test manipulation in commit 249df7cbdb09817fed0ddf80f01ba5af12466820 and makes all existing unit tests pass with smart_holder as default holder.
* GitHub CI clang-tidy fixes.
* Adding messages to terse `static_assert`s, for pre-C++17 compatibility.
* Using @pytest.mark.parametrize to run each assert separately (to see all errors, not just the first).
* Systematically removing _atyp from function names, to make the test code simpler.
* Using re.match to accommodate variable number of intermediate MvCtor.
* Also removing `operator T()` from smart_holder_type_caster, to fix gcc compilation errors. The only loss is pass_rref in test_class_sh_basic.
* Systematically replacing `detail::enable_if_t<...smart_holder...>` with `typename std::enable_if<...smart_holder...>::type`. Attempt to work around MSVC 2015 issues, to be tested via GitHub CI. The idea for this change originates from this comment: https://github.com/pybind/pybind11/issues/1616#issuecomment-444536813
* Importing re before pytest after observing a PyPy CI flake when importing pytest first.
* Copying MSVC 2015 compatibility change from branch pr2672_use_smart_holder_as_default.
* Introducing is_smart_holder_type_caster_base_tag, to keep smart_holder code more disconnected.
* Working around MSVC 2015 bug.
* Expanding comment for MSVC 2015 workaround.
* Systematically changing std::enable_if back to detail::enable_if_t, effectively reverting commit 5d4b6890a337ae1bbaec4091f4195606f89a3b06.
* Removing unused smart_holder_type_caster_load::loaded_as_rvalue_ref (it was an oversight that it was not removed with commit 23036a45eb4731a06b488ec1fdf83bca677b7f67).
* Removing py::classu, because it does not seem useful enough.
* Reverting commit 63495313066119dcf7510c2ae8b468b46c12ef8f by un-commenting `const` in `def_buffer(...)`. To make this possible, `operator T const&` and `operator T const*` in `smart_holder_type_caster` need to be marked as `const` member functions.
* Adding construct() overloads for constructing smart_holder from alias unique_ptr, shared_ptr returns.
* Adding test_class_sh_factory_constructors.cpp to tests/CMakeLists.txt (fixes oversight, this should have been added long before).
* Compatibility with old clang versions (clang 3.6, 3.7 C++11).
* Cleaning up changes to existing unit tests.
* Systematically adding SMART_HOLDER_WIP tag. Removing minor UNTESTED tags (only the throw are not actually exercised, investing time there has a high cost but very little benefit).
* Splitting out smart_holder_type_casters again, into new detail/smart_holder_type_casters_inline_include.h.
* Splitting out smart_holder_init_inline_include.h.
* Adding additional new include files to CMakeLists.txt, tests/extra_python_package/test_files.py.
* clang-format cleanup of most smart_holder code.
* Adding source code comments in response to review.
* Simple micro-benchmark ("ubench") comparing runtime performance for several holders.
Tested using github.com/rwgk/pybind11_scons and Google-internal build system.
Sorry, no cmake support at the moment.
First results: https://docs.google.com/spreadsheets/d/1InapCYws2Gt-stmFf_Bwl33eOMo3aLE_gc9adveY7RU/edit#gid=0
* Breaking out number_bucket.h, adding hook for also collecting performance data for PyCLIF.
* Accounting for ubench in MANIFEST.in (simply prune, for now).
* Smarter determination of call_repetitions.
[skip ci]
* Also scaling performance data to PyCLIF.
[skip ci]
* Adding ubench/python/number_bucket.clif here for general visibility.
* Fix after rebase
* Merging detail/smart_holder_init_inline_include.h into detail/init.h.
* Renaming detail/is_smart_holder_type_caster.h -> detail/smart_holder_sfinae_hooks_only.h.
* Renaming is_smart_holder_type_caster -> type_uses_smart_holder_type_caster for clarity.
* Renaming type_caster_type_is_smart_holder_type_caster -> wrapped_type_uses_smart_holder_type_caster for clarity.
* Renaming is_smart_holder_type_caster_base_tag -> smart_holder_type_caster_base_tag for simplicity.
* Adding copyright notices and minor colateral cleanup.
* iwyu cleanup (comprehensive only for cast.h and smart_holder*.h files).
* Fixing `git rebase master` accident.
* Moving large `pragma warning` block from pybind11.h to detail/common.h.
* Fixing another `git rebase master` accident.
2021-02-24 05:50:42 +00:00
|
|
|
template <typename type>
|
2024-07-20 06:55:22 +00:00
|
|
|
using make_caster = type_caster<intrinsic_t<type>>;
|
Adding py::smart_holder (for smart-pointer interoperability). (#2672)
* Adding test_unique_ptr_member (for desired PyCLIF behavior).
See also: https://github.com/pybind/pybind11/issues/2583
Does not build with upstream master or
https://github.com/pybind/pybind11/pull/2047, but builds with
https://github.com/RobotLocomotion/pybind11 and almost runs:
```
Running tests in directory "/usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests":
================================================================================= test session starts =================================================================================
platform linux -- Python 3.8.5, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests, inifile: pytest.ini
collected 2 items
test_unique_ptr_member.py .F [100%]
====================================================================================== FAILURES =======================================================================================
_____________________________________________________________________________ test_pointee_and_ptr_owner ______________________________________________________________________________
def test_pointee_and_ptr_owner():
obj = m.pointee()
assert obj.get_int() == 213
m.ptr_owner(obj)
with pytest.raises(ValueError) as exc_info:
> obj.get_int()
E Failed: DID NOT RAISE <class 'ValueError'>
test_unique_ptr_member.py:17: Failed
============================================================================= 1 failed, 1 passed in 0.06s =============================================================================
```
* unique_ptr or shared_ptr return
* new test_variant_unique_shared with vptr_holder prototype
* moving prototype code to pybind11/vptr_holder.h, adding type_caster specialization to make the bindings involving unique_ptr passing compile, but load and cast implementations are missing
* disabling GitHub Actions on pull_request (for this PR)
* disabling AppVeyor (for this PR)
* TRIGGER_SEGSEV macro, annotations for GET_STACK (vptr::get), GET_INT_STACK (pointee)
* adding test_promotion_of_disowned_to_shared
* Copying tests as-is from xxx_value_ptr_xxx_holder branch.
https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder
Systematically exercising returning and passing unique_ptr<T>, shared_ptr<T>
with unique_ptr, shared_ptr holder.
Observations:
test_holder_unique_ptr:
make_unique_pointee OK
pass_unique_pointee BUILD_FAIL (as documented)
make_shared_pointee Abort free(): double free detected
pass_shared_pointee RuntimeError: Unable to load a custom holder type from a default-holder instance
test_holder_shared_ptr:
make_unique_pointee Segmentation fault (#1138)
pass_unique_pointee BUILD_FAIL (as documented)
make_shared_pointee OK
pass_shared_pointee OK
* Copying tests as-is from xxx_value_ptr_xxx_holder branch.
https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder
Systematically exercising casting between shared_ptr<base>, shared_ptr<derived>.
* Demonstration of Undefined Behavior in handling of shared_ptr holder.
Based on https://godbolt.org/z/4fdjaW by jorgbrown@ (thanks Jorg!).
* Additional demonstration of Undefined Behavior in handling of shared_ptr holder.
* fixing up-down mixup in comment
* Demonstration of Undefined Behavior in handling of polymorphic pointers.
(This demo does NOT involve smart pointers at all, unlike the otherwise similar test_smart_ptr_private_first_base.)
* minor test_private_first_base.cpp simplification (after discovering that this can be wrapped with Boost.Python, using boost::noncopyable)
* pybind11 equivalent of Boost.Python test similar to reproducer under #1333
* Snapshot of WIP, TODO: shared_ptr deleter with on/off switch
* Adding vptr_deleter.
* Adding from/as unique_ptr<T> and unique_ptr<T, D>.
* Adding from_shared_ptr. Some polishing.
* New tests/core/smart_holder_poc_test.cpp, using Catch2.
* Adding in vptr_deleter_guard_flag.
* Improved labeling of TEST_CASEs.
* Shuffling existing TEST_CASEs into systematic matrix.
* Implementing all [S]uccess tests.
* Implementing all [E]xception tests.
* Testing of exceptions not covered by the from-as matrix.
* Adding top-level comment.
* Converting from methods to factory functions (no functional change).
* Removing obsolete and very incomplete test (replaced by Catch2-based test).
* Removing stray file.
* Adding type_caster_bare_interface_demo.
* Adding shared_ptr<mpty>, shared_ptr<mpty const> casters.
* Adding unique_ptr<mpty>, unique_ptr<mpty const> casters.
* Pure copy of `class class_` implementation in pybind11.h (master commit 98f1bbb8004f654ba9e26717bdf5912fb899b05a).
* classh.h: renaming of class_ to classh + namespace; forking test_classh_wip from test_type_caster_bare_interface_demo.
* Hard-coding smart_holder into classh.
* Adding mpty::mtxt string member.
* Adding isinstance<mpty> in type_caster::load functions.
* Adding rvalue_ref, renaming const_value_ref to lvalue_ref & removing const.
* Retrieving smart_holder pointer in type_caster<mpty>::load, and using it cast_op operators.
* Factoring out smart_holder_type_caster_load.
* Retrieving smart_holder pointer in type_caster<std::shared_ptr<mpty[ const]>>::load, and using it cast_op operators.
* Improved error messaging: Cannot disown nullptr (as_unique_ptr).
* Retrieving smart_holder pointer in type_caster<std::unique_ptr<mpty[ const]>>::load, and using it cast_op operators.
* Pure `clang-format --style=file -i` change.
* Pure `clang-format --style=file -i` change, with two `clang-format off` directives.
* Fixing oversight (discovered by flake8).
* flake8 cleanup
* Systematically setting mtxt for all rtrn_mpty_* functions (preparation, the values are not actually used yet).
* static cast handle for rtrn_cptr works by simply dropping in code from type_caster_base (marked with comments).
* static cast handle for rtrn_cref works by simply dropping in code from type_caster_base (marked with comments). rtrn_mref and rtrn_mptr work via const_cast (to add const).
* static cast handle for rtrn_valu works by simply dropping in code from type_caster_base (marked with comments). rtrn_rref raises a RuntimeError, to be investigated.
* Copying type_caster_generic::cast into type_caster<mpty> as-is (preparation for handling smart pointers).
* Pure clang-format change (applied to original type_caster_generic::cast).
* Adding comment re potential use_count data race.
* static handle cast implementations for rtrn_shmp, rtrn_shcp.
* Adding MISSING comments in operator std::unique_ptr<mpty[ const]>.
* static handle cast implementations for rtrn_uqmp, rtrn_uqcp.
* Bug fix: vptr_deleter_armed_flag_ptr has to live on the heap.
See new bullet point in comment section near the top.
The variable was also renamed to reflect its function more accurately.
* Fixing bugs discovered by ASAN. The code is now ASAN, MSAN, UBSAN clean.
* Making test_type_caster_bare_interface_demo.cpp slightly more realistic, ASAN, MSAN, UBSAN clean.
* Calling deregister_instance after disowning via unique_ptr.
* Removing enable_shared_from_this stub, simplifying existing code, clang-format.
Open question, with respect to the original code:
https://github.com/pybind/pybind11/blob/76a160070b369f8d82b945c97924227e8b835c94/include/pybind11/pybind11.h#L1510
To me it looks like the exact situation marked as `std::shared_ptr<Good> gp1 = not_so_good.getptr();` here: https://en.cppreference.com/w/cpp/memory/enable_shared_from_this
The comment there is: `// undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17)`
Does the existing code have UB pre C++17?
I'll leave handling of enable_shared_from_this for later, as the need arises.
* Cosmetical change around helper functions.
* Using type_caster_base<mpty>::src_and_type directly, removing copy. Also renaming one cast to cast_const_raw_ptr, for clarity.
* Fixing clang-format oversight.
* Using factored-out make_constructor (PR #2798), removing duplicate code.
* Inserting additional assert to ensure a returned unique_ptr is always a new Python instance.
* Adding minor comment (change to internals needed to distinguish uninitialized/disowned in error message).
* Factoring out find_existing_python_instance().
* Moving factored-out make_constructor to test_classh_wip.cpp, restoring previous version of cast.h. This is currently the most practical approach. See PR #2798 for background.
* Copying classh type_casters from test_classh_wip.cpp UNMODIFIED, as a baseline for generalizing the code.
* Using pybind11/detail/classh_type_casters.h from test_classh_wip.cpp.
* Adding & using PYBIND11_CLASSH_TYPE_CASTERS define.
* Adding test_classh_inheritance, currently failing (passes with class_).
* Removing .clang-format before git rebase master (where the file was added).
* Bringing back .clang-format, the previous rm was a bad idea.
* Folding in modified_type_caster_generic_load_impl, just enough to pass test_class_wip. test_classh_inheritance is still failing, but with a different error: [RuntimeError: Incompatible type (as_raw_ptr_unowned).]
* Minimal changes needed to pass test_classh_inheritance.
* First pass adjusting try_implicit_casts and try_load_foreign_module_local to capture loaded_v_h, but untested and guarded with pybind11_failure("Untested"). This was done mainly to determine general feasibility. Note the TODO in pybind11.h, where type_caster_generic::local_load is currently hard-coded. test_classh_wip and test_classh_inheritance still pass, as before.
* Decoupling generic_type from type_caster_generic.
* Changes and tests covering classh_type_casters try_implicit_casts.
* Minimal test covering classh_type_casters load_impl Case 2b.
* Removing stray isinstance<T>(src): it interferes with the py::module_local feature. Adding missing #includes.
* Tests for classh py::module_local() feature.
* Pure renaming of function names in test_classh_inheritance, similar to the systematic approach used in test_class_wip. NO functional changes.
* Pure renaming of function and variable names, for better generalization when convoluting with inheritance. NO functional changes.
* Adopting systematic naming scheme from test_classh_wip. NO functional changes.
* Moving const after type name, for functions that cover a systematic scheme. NO functional changes.
* Adding smart_holder_type_caster_load::loaded_as_shared_ptr, currently bypassing smart_holder shared_ptr tracking completely, but the tests pass and are sanitizer clean.
* Removing rtti_held from smart_holder. See updated comment.
* Cleaning up loaded_as_raw_ptr_unowned, loaded_as_shared_ptr.
* Factoring out convert_type and folding into loaded_as_unique_ptr.
* Folding convert_type into lvalue_ref and rvalue_ref paths. Some smart_holder_type_caster_load cleanup.
* Using unique_ptr in local_load to replace static variable. Also adding local_load_safety_guard.
* Converting test_unique_ptr_member to using classh: fully working, ASAN, MSAN, UBSAN clean.
* Removing debugging comments (GET_STACK, GET_INT_STACK). cast.h is identical to current master again, pybind11.h only has the generic_type::initialize(..., &type_caster_generic::local_load) change.
* Purging obsolete pybind11/vptr_holder.h and associated test.
* Moving several tests to github.com/rwgk/rwgk_tbx/tree/main/pybind11_tests
https://github.com/rwgk/rwgk_tbx/commit/a2c2f88174a30f5de80d7d26e0f77c7b60f5fb85
These tests are from experimenting, and for demonstrating UB in pybind11 multiple inheritance handling ("first_base"), to be fixed later.
* Adding py::smart_holder support to py::class_, purging py::classh completely.
* Renaming files in include directory, creating pybind11/smart_holder.h.
* Renaming all "classh" to "smart_holder" in pybind11/detail/smart_holder_type_casters.h.
The user-facing macro is now PYBIND11_SMART_HOLDER_TYPE_CASTERS.
* Systematically renaming tests to use "class_sh" in the name.
* Renaming test_type_caster_bare_interface_demo to test_type_caster_bare_interface.
* Renaming new tests/core subdirectory to tests/pure_cpp.
* Adding new tests to CMake config, resetting CI config.
* Changing CMake file so that test_class_sh_module_local.py actually runs.
* clang-tidy fixes.
* 32-bit compatibility.
* Reusing type_caster_base make_copy_constructor, make_move_constructor with a trick.
* CMake COMPARE NATURAL is not available with older versions.
* Adding copyright notices to new header files.
* Explicitly define copy/move constructors/assignments.
* Adding new header files to tests/extra_python_package/test_files.py.
* Adding tests/pure_cpp/CMakeLists.txt.
* Making use of the new find_existing_python_instance() function factored out with PR #2822.
* Moving define PYBIND11_SMART_HOLDER_TYPE_CASTERS(T) down in the file. NO functional changes. Preparation for follow-up work (to keep that diff smaller).
* Reintroducing py::classh, this time as a simple alias for py::class_<U, py::smart_holder>.
* Replacing detail::is_smart_holder<H> in cast.h with detail::is_smart_holder_type_caster<T>.
Moving get_local_load_function_ptr, init_instance_for_type to smart_holder_type_caster_class_hooks.
Expanding static_assert in py::type::handle_of<> to accommodate smart_holder_type_casters.
* Fixing oversight.
* Adding classu alias for class_<U, std::unique_ptr<U>>.
* Giving up on idea to use legacy init_instance only if is_base_of<type_caster_generic, type_caster<T>. There are use cases in the wild that define both a custom type_caster and class_.
* Removing test_type_caster_bare_interface, which was moved to the separate PR #2834.
* Moving up is_smart_holder_type_caster, to also use in cast_is_temporary_value_reference.
* Adding smart_holder_type_casters for unique_ptr with custom deleter. SEVERE CODE DUPLICATION. This commit is to establish a baseline for consolidating the unique_ptr code.
* Unification of unique_ptr, unique_ptr_with_deleter code in smart_holder_poc.h. Leads to more fitting error messages. Enables use of unique_ptr<T, D> smart_holder_type_casters also for unique_ptr<T>.
* Copying files as-is from branch test_unique_ptr_member (PR #2672).
* Adding comment, simplifying naming, cmake addition.
* Introducing PYBIND11_USE_SMART_HOLDER_AS_DEFAULT macro (tested only undefined; there are many errors with the macro defined).
* Removing test_type_caster_bare_interface, which was moved to the separate PR #2834.
* Fixing oversight introduced with commit 95425f13d6c14fcb6ee479b62b602dc8a605ec49.
* Setting record.default_holder correctly for PYBIND11_USE_SMART_HOLDER_AS_DEFAULT.
With this test_class.cpp builds and even mostly runs, except
`test_multiple_instances_with_same_pointer`, which segfaults because it is
using a `unique_ptr` holder but `smart_holder` `type_caster`.
Also adding `static_assert`s to generate build errors for such situations,
but guarding with `#if 0` to first pivot to test_factory_constructors.cpp.
* Fixing up cast.h and smart_holder.h after rebase.
* Removing detail/smart_holder_type_casters.h in separate commit.
* Commenting out const in def_buffer(... const). With this, test_buffers builds and runs with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT. Explanation why the const needs to be removed, or fix elsewhere, is still needed, but left for later.
* Adding test_class_sh_factory_constructors, reproducing test_factory_constructors failure. Using py::class_ in this commit, to be changed to py::classh for debugging.
* Removing include/pybind11/detail/smart_holder_type_casters.h from CMakeLists.txt, test_files.py (since it does not exist in this branch).
* Adding // DANGER ZONE reminders.
* Converting as many py::class_ to py::classh as possible, not breaking tests.
* Adding initimpl::construct() overloads, resulting in test_class_sh_factory_constructors feature parity for py::class_ and py::classh.
* Adding enable_if !is_smart_holder_type_caster to existing initimpl::construct(). With this test_factory_constructors.cpp builds with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT.
* Disabling shared_ptr&, shared_ptr* tests when building with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT for now, pending work on smart_holder_type_caster<shared_ptr>.
* Factoring out struct and class definitions into anonymous namespace. Preparation for building with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT.
* Simplifying from_unique_ptr(): typename D = std::default_delete<T> is not needed. Factoring out is_std_default_delete<T>() for consistentcy between ensure_compatible_rtti_uqp_del() and from_unique_ptr().
* Introducing PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS. Using it in test_smart_ptr.cpp. With this test_smart_ptr builds with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT and all but one test run successfully.
* Introducing 1. type_caster_for_class_, used in PYBIND11_MAKE_OPAQUE, and 2. default_holder_type, used in stl_bind.h.
* Using __VA_ARGS__ in PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS.
* Replacing condense_for_macro with much simpler approach.
* Softening static_assert, to only check specifically that smart_holder is not mixed with type_caster_base, and unique_ptr/shared_ptr holders are not mixed with smart_holder_type_casters.
* Adding PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS in test_class.cpp (with this all but one test succeed with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT).
* Adding remaining PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS. static_assert for "necessary conditions" for both types of default holder, static_assert for "strict conditions" guarded by new PYBIND11_STRICT_ASSERTS_CLASS_HOLDER_VS_TYPE_CASTER_MIX. All tests build & run as before with unique_ptr as the default holder, all tests build for smart_holder as the default holder, even with the strict static_assert.
* Introducing check_is_smart_holder_type_caster() function for runtime check, and reinterpreting record.default_holder as "uses_unique_ptr_holder". With this test_smart_ptr succeeds. (All 42 tests build, 35 tests succeed, 5 run but have some failures, 2 segfault.)
* Bug fix: Adding have_value() to smart_holder_type_caster_load. With this test_builtin_casters succeeds. (All 42 tests build, 36 tests succeed, 5 run but have some failures, 1 segfault.)
* Adding unowned_void_ptr_from_direct_conversion to modified_type_caster_generic_load_impl. This fixes the last remaining segfault (test_numpy_dtypes). New stats for all tests combined: 12 failed, 458 passed.
* Adding "Lazy allocation for unallocated values" (for old-style __init__) into load_value_and_holder. Deferring destruction of disowned holder until clear_instance, to remain inspectable for "uninitialized" or "disowned" detection. New stats for all tests combined: 5 failed, 465 passed.
* Changing std::shared_ptr pointer/reference to const pointer/reference. New stats for all tests combined: 4 failed, 466 passed.
* Adding return_value_policy::move to permissible policies for unique_ptr returns. New stats for all tests combined: 3 failed, 467 passed.
* Overlooked flake8 fixes.
* Manipulating failing ConstructorStats test to pass, to be able to run all tests with ASAN.
This version of the code is ASAN clean with unique_ptr or smart_holder as the default.
This change needs to be reverted after adopting the existing move-only-if-refcount-is-1
logic used by type_caster_base.
* Adding copy constructor and move constructor tracking to atyp. Preparation for a follow-up change in smart_holder_type_caster, to make this test sensitive to the changing behavior.
[skip ci]
* Removing `operator T&&() &&` from smart_holder_type_caster, for compatibility with the behavior of type_caster_base. Enables reverting 2 of 3 test manipulations applied under commit 249df7cbdb09817fed0ddf80f01ba5af12466820. The manipulation in test_factory_constructors.py is NOT reverted in this commit.
[skip ci]
* Fixing unfortunate editing mishap. This reverts the last remaining test manipulation in commit 249df7cbdb09817fed0ddf80f01ba5af12466820 and makes all existing unit tests pass with smart_holder as default holder.
* GitHub CI clang-tidy fixes.
* Adding messages to terse `static_assert`s, for pre-C++17 compatibility.
* Using @pytest.mark.parametrize to run each assert separately (to see all errors, not just the first).
* Systematically removing _atyp from function names, to make the test code simpler.
* Using re.match to accommodate variable number of intermediate MvCtor.
* Also removing `operator T()` from smart_holder_type_caster, to fix gcc compilation errors. The only loss is pass_rref in test_class_sh_basic.
* Systematically replacing `detail::enable_if_t<...smart_holder...>` with `typename std::enable_if<...smart_holder...>::type`. Attempt to work around MSVC 2015 issues, to be tested via GitHub CI. The idea for this change originates from this comment: https://github.com/pybind/pybind11/issues/1616#issuecomment-444536813
* Importing re before pytest after observing a PyPy CI flake when importing pytest first.
* Copying MSVC 2015 compatibility change from branch pr2672_use_smart_holder_as_default.
* Introducing is_smart_holder_type_caster_base_tag, to keep smart_holder code more disconnected.
* Working around MSVC 2015 bug.
* Expanding comment for MSVC 2015 workaround.
* Systematically changing std::enable_if back to detail::enable_if_t, effectively reverting commit 5d4b6890a337ae1bbaec4091f4195606f89a3b06.
* Removing unused smart_holder_type_caster_load::loaded_as_rvalue_ref (it was an oversight that it was not removed with commit 23036a45eb4731a06b488ec1fdf83bca677b7f67).
* Removing py::classu, because it does not seem useful enough.
* Reverting commit 63495313066119dcf7510c2ae8b468b46c12ef8f by un-commenting `const` in `def_buffer(...)`. To make this possible, `operator T const&` and `operator T const*` in `smart_holder_type_caster` need to be marked as `const` member functions.
* Adding construct() overloads for constructing smart_holder from alias unique_ptr, shared_ptr returns.
* Adding test_class_sh_factory_constructors.cpp to tests/CMakeLists.txt (fixes oversight, this should have been added long before).
* Compatibility with old clang versions (clang 3.6, 3.7 C++11).
* Cleaning up changes to existing unit tests.
* Systematically adding SMART_HOLDER_WIP tag. Removing minor UNTESTED tags (only the throw are not actually exercised, investing time there has a high cost but very little benefit).
* Splitting out smart_holder_type_casters again, into new detail/smart_holder_type_casters_inline_include.h.
* Splitting out smart_holder_init_inline_include.h.
* Adding additional new include files to CMakeLists.txt, tests/extra_python_package/test_files.py.
* clang-format cleanup of most smart_holder code.
* Adding source code comments in response to review.
* Simple micro-benchmark ("ubench") comparing runtime performance for several holders.
Tested using github.com/rwgk/pybind11_scons and Google-internal build system.
Sorry, no cmake support at the moment.
First results: https://docs.google.com/spreadsheets/d/1InapCYws2Gt-stmFf_Bwl33eOMo3aLE_gc9adveY7RU/edit#gid=0
* Breaking out number_bucket.h, adding hook for also collecting performance data for PyCLIF.
* Accounting for ubench in MANIFEST.in (simply prune, for now).
* Smarter determination of call_repetitions.
[skip ci]
* Also scaling performance data to PyCLIF.
[skip ci]
* Adding ubench/python/number_bucket.clif here for general visibility.
* Fix after rebase
* Merging detail/smart_holder_init_inline_include.h into detail/init.h.
* Renaming detail/is_smart_holder_type_caster.h -> detail/smart_holder_sfinae_hooks_only.h.
* Renaming is_smart_holder_type_caster -> type_uses_smart_holder_type_caster for clarity.
* Renaming type_caster_type_is_smart_holder_type_caster -> wrapped_type_uses_smart_holder_type_caster for clarity.
* Renaming is_smart_holder_type_caster_base_tag -> smart_holder_type_caster_base_tag for simplicity.
* Adding copyright notices and minor colateral cleanup.
* iwyu cleanup (comprehensive only for cast.h and smart_holder*.h files).
* Fixing `git rebase master` accident.
* Moving large `pragma warning` block from pybind11.h to detail/common.h.
* Fixing another `git rebase master` accident.
2021-02-24 05:50:42 +00:00
|
|
|
|
2016-11-25 17:35:00 +00:00
|
|
|
// Shortcut for calling a caster's `cast_op_type` cast operator for casting a type_caster to a T
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
typename make_caster<T>::template cast_op_type<T> cast_op(make_caster<T> &caster) {
|
2023-10-21 17:50:14 +00:00
|
|
|
using result_t = typename make_caster<T>::template cast_op_type<T>; // See PR #4893
|
|
|
|
return caster.operator result_t();
|
2016-11-25 17:35:00 +00:00
|
|
|
}
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
typename make_caster<T>::template cast_op_type<typename std::add_rvalue_reference<T>::type>
|
2017-05-14 19:57:26 +00:00
|
|
|
cast_op(make_caster<T> &&caster) {
|
2023-10-21 17:50:14 +00:00
|
|
|
using result_t = typename make_caster<T>::template cast_op_type<
|
|
|
|
typename std::add_rvalue_reference<T>::type>; // See PR #4893
|
|
|
|
return std::move(caster).operator result_t();
|
2016-11-25 17:35:00 +00:00
|
|
|
}
|
|
|
|
|
2024-07-31 21:06:39 +00:00
|
|
|
template <typename EnumType>
|
|
|
|
class type_caster_enum_type {
|
|
|
|
private:
|
|
|
|
using Underlying = typename std::underlying_type<EnumType>::type;
|
|
|
|
|
|
|
|
public:
|
|
|
|
static constexpr auto name = const_name<EnumType>();
|
|
|
|
|
|
|
|
template <typename SrcType>
|
|
|
|
static handle cast(SrcType &&src, return_value_policy, handle parent) {
|
|
|
|
handle native_enum
|
|
|
|
= global_internals_native_enum_type_map_get_item(std::type_index(typeid(EnumType)));
|
|
|
|
if (native_enum) {
|
|
|
|
return native_enum(static_cast<Underlying>(src)).release();
|
|
|
|
}
|
2024-07-31 21:38:30 +00:00
|
|
|
return type_caster_base<EnumType>::cast(
|
2024-07-31 21:06:39 +00:00
|
|
|
std::forward<SrcType>(src),
|
|
|
|
// Fixes https://github.com/pybind/pybind11/pull/3643#issuecomment-1022987818:
|
|
|
|
return_value_policy::copy,
|
|
|
|
parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool load(handle src, bool convert) {
|
|
|
|
handle native_enum
|
|
|
|
= global_internals_native_enum_type_map_get_item(std::type_index(typeid(EnumType)));
|
|
|
|
if (native_enum) {
|
|
|
|
if (!isinstance(src, native_enum)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
type_caster<Underlying> underlying_caster;
|
|
|
|
if (!underlying_caster.load(src.attr("value"), convert)) {
|
|
|
|
pybind11_fail("native_enum internal consistency failure.");
|
|
|
|
}
|
|
|
|
value = static_cast<EnumType>(static_cast<Underlying>(underlying_caster));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (!pybind11_enum_) {
|
2024-07-31 21:38:30 +00:00
|
|
|
pybind11_enum_.reset(new type_caster_base<EnumType>());
|
2024-07-31 21:06:39 +00:00
|
|
|
}
|
|
|
|
return pybind11_enum_->load(src, convert);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
using cast_op_type = detail::cast_op_type<T>;
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
|
|
operator EnumType *() {
|
|
|
|
if (!pybind11_enum_) {
|
|
|
|
return &value;
|
|
|
|
}
|
|
|
|
return pybind11_enum_->operator EnumType *();
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
|
|
operator EnumType &() {
|
|
|
|
if (!pybind11_enum_) {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
return pybind11_enum_->operator EnumType &();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2024-07-31 21:38:30 +00:00
|
|
|
std::unique_ptr<type_caster_base<EnumType>> pybind11_enum_;
|
2024-07-31 21:06:39 +00:00
|
|
|
EnumType value;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename EnumType, typename SFINAE = void>
|
|
|
|
struct type_caster_enum_type_enabled : std::true_type {};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct type_uses_type_caster_enum_type {
|
|
|
|
static constexpr bool value
|
|
|
|
= std::is_enum<T>::value && type_caster_enum_type_enabled<T>::value;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename EnumType>
|
|
|
|
class type_caster<EnumType, detail::enable_if_t<type_uses_type_caster_enum_type<EnumType>::value>>
|
|
|
|
: public type_caster_enum_type<EnumType> {};
|
|
|
|
|
|
|
|
template <typename T, detail::enable_if_t<std::is_enum<T>::value, int> = 0>
|
|
|
|
bool isinstance_native_enum_impl(handle obj, const std::type_info &tp) {
|
|
|
|
handle native_enum = global_internals_native_enum_type_map_get_item(tp);
|
|
|
|
if (!native_enum) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return isinstance(obj, native_enum);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T, detail::enable_if_t<!std::is_enum<T>::value, int> = 0>
|
|
|
|
bool isinstance_native_enum_impl(handle, const std::type_info &) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
bool isinstance_native_enum(handle obj, const std::type_info &tp) {
|
|
|
|
return isinstance_native_enum_impl<intrinsic_t<T>>(obj, tp);
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename type>
|
|
|
|
class type_caster<std::reference_wrapper<type>> {
|
2017-05-12 17:40:05 +00:00
|
|
|
private:
|
|
|
|
using caster_t = make_caster<type>;
|
|
|
|
caster_t subcaster;
|
2022-02-10 20:17:07 +00:00
|
|
|
using reference_t = type &;
|
|
|
|
using subcaster_cast_op_type = typename caster_t::template cast_op_type<reference_t>;
|
|
|
|
|
|
|
|
static_assert(
|
|
|
|
std::is_same<typename std::remove_const<type>::type &, subcaster_cast_op_type>::value
|
|
|
|
|| std::is_same<reference_t, subcaster_cast_op_type>::value,
|
|
|
|
"std::reference_wrapper<T> caster requires T to have a caster with an "
|
|
|
|
"`operator T &()` or `operator const T &()`");
|
|
|
|
|
2016-04-20 15:00:57 +00:00
|
|
|
public:
|
2017-05-12 17:40:05 +00:00
|
|
|
bool load(handle src, bool convert) { return subcaster.load(src, convert); }
|
2017-07-02 09:48:56 +00:00
|
|
|
static constexpr auto name = caster_t::name;
|
2022-02-10 20:17:07 +00:00
|
|
|
static handle
|
|
|
|
cast(const std::reference_wrapper<type> &src, return_value_policy policy, handle parent) {
|
2017-05-12 17:40:05 +00:00
|
|
|
// It is definitely wrong to take ownership of this pointer, so mask that rvp
|
2022-02-08 00:23:20 +00:00
|
|
|
if (policy == return_value_policy::take_ownership
|
|
|
|
|| policy == return_value_policy::automatic) {
|
2017-05-12 17:40:05 +00:00
|
|
|
policy = return_value_policy::automatic_reference;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2017-05-12 17:40:05 +00:00
|
|
|
return caster_t::cast(&src.get(), policy, parent);
|
2016-04-20 15:00:57 +00:00
|
|
|
}
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
using cast_op_type = std::reference_wrapper<type>;
|
CodeHealth: Enabling clang-tidy google-explicit-constructor (#3250)
* Adding google-explicit-constructor to .clang-tidy
* clang-tidy explicit attr.h (all automatic)
* clang-tidy explicit cast.h (all automatic)
* clang-tidy detail/init.h (1 NOLINT)
* clang-tidy detail/type_caster_base.h (2 NOLINT)
* clang-tidy pybind11.h (7 NOLINT)
* clang-tidy detail/common.h (3 NOLINT)
* clang-tidy detail/descr.h (2 NOLINT)
* clang-tidy pytypes.h (23 NOLINT, only 1 explicit)
* clang-tidy eigen.h (7 NOLINT, 0 explicit)
* Adding 2 explicit in functional.h
* Adding 4 explicit in iostream.h
* clang-tidy numpy.h (1 NOLINT, 1 explicit)
* clang-tidy embed.h (0 NOLINT, 1 explicit)
* clang-tidy tests/local_bindings.h (0 NOLINT, 4 explicit)
* clang-tidy tests/pybind11_cross_module_tests.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/pybind11_tests.h (0 NOLINT, 2 explicit)
* clang-tidy tests/test_buffers.cpp (0 NOLINT, 2 explicit)
* clang-tidy tests/test_builtin_casters.cpp (0 NOLINT, 4 explicit)
* clang-tidy tests/test_class.cpp (0 NOLINT, 6 explicit)
* clang-tidy tests/test_copy_move.cpp (0 NOLINT, 7 explicit)
* clang-tidy tests/test_embed/external_module.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/test_embed/test_interpreter.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/object.h (0 NOLINT, 2 explicit)
* clang-tidy batch of fully automatic fixes.
* Workaround for MSVC 19.16.27045.0 C++17 Python 2 C++ syntax error.
2021-09-09 01:53:38 +00:00
|
|
|
explicit operator std::reference_wrapper<type>() { return cast_op<type &>(subcaster); }
|
2016-04-20 15:00:57 +00:00
|
|
|
};
|
|
|
|
|
2021-07-09 13:45:53 +00:00
|
|
|
#define PYBIND11_TYPE_CASTER(type, py_name) \
|
|
|
|
protected: \
|
|
|
|
type value; \
|
|
|
|
\
|
|
|
|
public: \
|
|
|
|
static constexpr auto name = py_name; \
|
2022-02-25 21:25:23 +00:00
|
|
|
template <typename T_, \
|
|
|
|
::pybind11::detail::enable_if_t< \
|
|
|
|
std::is_same<type, ::pybind11::detail::remove_cv_t<T_>>::value, \
|
2022-12-06 18:10:48 +00:00
|
|
|
int> \
|
|
|
|
= 0> \
|
2022-02-25 21:25:23 +00:00
|
|
|
static ::pybind11::handle cast( \
|
|
|
|
T_ *src, ::pybind11::return_value_policy policy, ::pybind11::handle parent) { \
|
2021-07-09 13:45:53 +00:00
|
|
|
if (!src) \
|
2022-02-25 21:25:23 +00:00
|
|
|
return ::pybind11::none().release(); \
|
|
|
|
if (policy == ::pybind11::return_value_policy::take_ownership) { \
|
2021-07-09 13:45:53 +00:00
|
|
|
auto h = cast(std::move(*src), policy, parent); \
|
|
|
|
delete src; \
|
|
|
|
return h; \
|
|
|
|
} \
|
|
|
|
return cast(*src, policy, parent); \
|
|
|
|
} \
|
2021-08-06 18:30:28 +00:00
|
|
|
operator type *() { return &value; } /* NOLINT(bugprone-macro-parentheses) */ \
|
|
|
|
operator type &() { return value; } /* NOLINT(bugprone-macro-parentheses) */ \
|
|
|
|
operator type &&() && { return std::move(value); } /* NOLINT(bugprone-macro-parentheses) */ \
|
2021-07-09 13:45:53 +00:00
|
|
|
template <typename T_> \
|
2022-02-25 21:25:23 +00:00
|
|
|
using cast_op_type = ::pybind11::detail::movable_cast_op_type<T_>
|
2015-12-16 11:11:01 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename CharT>
|
|
|
|
using is_std_char_type = any_of<std::is_same<CharT, char>, /* std::string */
|
2019-12-19 11:16:24 +00:00
|
|
|
#if defined(PYBIND11_HAS_U8STRING)
|
2022-02-10 20:17:07 +00:00
|
|
|
std::is_same<CharT, char8_t>, /* std::u8string */
|
2019-12-19 11:16:24 +00:00
|
|
|
#endif
|
2022-02-10 20:17:07 +00:00
|
|
|
std::is_same<CharT, char16_t>, /* std::u16string */
|
|
|
|
std::is_same<CharT, char32_t>, /* std::u32string */
|
|
|
|
std::is_same<CharT, wchar_t> /* std::wstring */
|
|
|
|
>;
|
2020-09-10 15:49:26 +00:00
|
|
|
|
2015-11-30 11:30:28 +00:00
|
|
|
template <typename T>
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
struct type_caster<T, enable_if_t<std::is_arithmetic<T>::value && !is_std_char_type<T>::value>> {
|
2017-02-04 01:16:14 +00:00
|
|
|
using _py_type_0 = conditional_t<sizeof(T) <= sizeof(long), long, long long>;
|
2022-02-10 20:17:07 +00:00
|
|
|
using _py_type_1 = conditional_t<std::is_signed<T>::value,
|
|
|
|
_py_type_0,
|
|
|
|
typename std::make_unsigned<_py_type_0>::type>;
|
2017-02-04 01:16:14 +00:00
|
|
|
using py_type = conditional_t<std::is_floating_point<T>::value, double, _py_type_1>;
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
public:
|
2017-02-04 01:16:14 +00:00
|
|
|
bool load(handle src, bool convert) {
|
2015-11-30 11:30:28 +00:00
|
|
|
py_type py_value;
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!src) {
|
2016-05-10 14:59:01 +00:00
|
|
|
return false;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2017-02-04 01:16:14 +00:00
|
|
|
|
2021-01-17 01:52:14 +00:00
|
|
|
#if !defined(PYPY_VERSION)
|
|
|
|
auto index_check = [](PyObject *o) { return PyIndex_Check(o); };
|
|
|
|
#else
|
|
|
|
// In PyPy 7.3.3, `PyIndex_Check` is implemented by calling `__index__`,
|
|
|
|
// while CPython only considers the existence of `nb_index`/`__index__`.
|
|
|
|
auto index_check = [](PyObject *o) { return hasattr(o, "__index__"); };
|
|
|
|
#endif
|
|
|
|
|
2017-02-04 01:16:14 +00:00
|
|
|
if (std::is_floating_point<T>::value) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (convert || PyFloat_Check(src.ptr())) {
|
2017-02-04 01:16:14 +00:00
|
|
|
py_value = (py_type) PyFloat_AsDouble(src.ptr());
|
2022-02-08 00:23:20 +00:00
|
|
|
} else {
|
2017-02-04 01:16:14 +00:00
|
|
|
return false;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2021-08-06 18:30:28 +00:00
|
|
|
} else if (PyFloat_Check(src.ptr())
|
|
|
|
|| (!convert && !PYBIND11_LONG_CHECK(src.ptr()) && !index_check(src.ptr()))) {
|
2021-01-17 01:52:14 +00:00
|
|
|
return false;
|
2021-01-25 20:05:17 +00:00
|
|
|
} else {
|
|
|
|
handle src_or_index = src;
|
2021-11-17 14:44:19 +00:00
|
|
|
// PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
|
feat: remove Python 3.7 support (#5191)
* First pass updating misc files, informed by https://github.com/pybind/pybind11/pull/5177/commits
* Remove jobs using silkeh/clang and gcc docker containers that come with Python 3.7
* Add silkeh/clang:17-bookworm
* Add job using GCC 7
* Revert "Add job using GCC 7"
This reverts commit 518515a761ac37dc2cf5d0980da82d0de39edc28.
* Try running in ubuntu-18.04 container under ubuntu-latest (to get GCC 7)
* Fix `-` vs `:` mixup.
* This reverts commit b1c4304475b8ad129c12330c7ed7eb85d15ba14a.
Revert "Try running in ubuntu:18.04 container under ubuntu-latest (to get GCC 7)"
This reverts commit b203a294bb444fc6ae57a0100fa91dc91b8d3264.
* `git grep 0x03080000` cleanup.
* `git grep -I -E '3\.7'` cleanup.
Removes two changes made under pybind/pybind11#3702
* Revert "`git grep -I -E '3\.7'` cleanup."
This reverts commit bb5b9d187bffbfb61e2977d7eee46b766fa1cce9.
* Remove comments that are evidently incorrect:
```
...
-- The CXX compiler identification is Clang 15.0.7
...
- Found Python: /usr/bin/python3.9 (found suitable version "3.9.2", minimum required is "3.7") found components: Interpreter Development.Module Development.Embed
...
/__w/pybind11/pybind11/include/pybind11/gil.h:150:13: error: 'auto key' can be declared as 'auto *key' [readability-qualified-auto,-warnings-as-errors]
auto key = internals.tstate;
^~~~~
auto *
/__w/pybind11/pybind11/include/pybind11/gil.h:174:13: error: 'auto key' can be declared as 'auto *key' [readability-qualified-auto,-warnings-as-errors]
auto key = detail::get_internals().tstate;
^~~~~
auto *
```
* .github/workflows/configure.yml: Change from Python 3.7 to 3.8
* Misc cleanup pass
* Miscellaneous changes based on manual review of the `git grep` matches below:
```
git_grep_37_38.sh |& sort | uniq -c
```
With git_grep_37_38.sh:
```
set -x
git grep 0x0307
git grep 0x0308
git grep PY_MINOR_VERSION
git grep PYPY_VERSION
git grep -I -E '3\.7'
git grep -I -E '3\.8'
git grep -I -E '\(3, 7'
git grep -I -E '\(3, 8'
git grep -I -E '3[^A-Za-z0-9.]+7'
git grep -I -E '3[^A-Za-z0-9.]+8'
```
Output:
```
1 .appveyor.yml: $env:CMAKE_INCLUDE_PATH = "eigen-3.3.7;$env:CMAKE_INCLUDE_PATH"
1 .appveyor.yml: 7z x eigen-3.3.7.zip -y > $null
1 .appveyor.yml: Start-FileDownload 'https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.zip'
1 CMakeLists.txt: # Bug in macOS CMake < 3.7 is unable to download catch
1 CMakeLists.txt: elseif(WINDOWS AND CMAKE_VERSION VERSION_LESS 3.8)
1 CMakeLists.txt: if(OSX AND CMAKE_VERSION VERSION_LESS 3.7)
1 CMakeLists.txt: message(WARNING "CMAKE 3.7+ needed on macOS to download catch, and newer HIGHLY recommended")
1 CMakeLists.txt: message(WARNING "CMAKE 3.8+ tested on Windows, previous versions untested")
1 CMakeLists.txt: # Only tested with 3.8+ in CI.
1 docs/advanced/functions.rst:Python 3.8 introduced a new positional-only argument syntax, using ``/`` in the
1 docs/changelog.rst:* Adapt pybind11 to a C API convention change in Python 3.8. `#1950
1 docs/changelog.rst:* Allow thread termination to be avoided during shutdown for CPython 3.7+ via
1 docs/changelog.rst: considered as conversion, consistent with Python 3.8+.
1 docs/changelog.rst: CPython 3.8 and 3.9 debug builds.
1 docs/changelog.rst:* Enum now has an ``__index__`` method on Python <3.8 too.
1 docs/changelog.rst: on Python 3.8. `#1780 <https://github.com/pybind/pybind11/pull/1780>`_.
1 docs/changelog.rst:* PyPy 3.10 support was added, PyPy 3.7 support was dropped.
2 docs/changelog.rst:* Support PyPy 7.3.7 and the PyPy3.8 beta. Test python-3.11 on PRs with the
1 docs/changelog.rst:* Use ``macos-13`` (Intel) for CI jobs for now (will drop Python 3.7 soon).
1 docs/changelog.rst:* Use new Python 3.7 Thread Specific Storage (TSS) implementation if available.
1 docs/compiling.rst: cmake -DPYBIND11_PYTHON_VERSION=3.8 ..
1 docs/compiling.rst: find_package(Python 3.8 COMPONENTS Interpreter Development REQUIRED)
1 docs/limitations.rst:- PyPy3 7.3.1 and 7.3.2 have issues with several tests on 32-bit Windows.
1 docs/requirements.txt:idna==3.7 \
1 + git grep 0x0307
1 + git grep 0x0308
1 + git grep -I -E '\(3, 7'
1 + git grep -I -E '3\.7'
1 + git grep -I -E '\(3, 8'
1 + git grep -I -E '3\.8'
1 + git grep -I -E '3[^A-Za-z0-9.]+7'
1 + git grep -I -E '3[^A-Za-z0-9.]+8'
1 + git grep PY_MINOR_VERSION
1 + git grep PYPY_VERSION
2 .github/workflows/ci.yml: - '3.8'
1 .github/workflows/ci.yml: - 3.8
1 .github/workflows/ci.yml: - name: Add Python 3.8
1 .github/workflows/ci.yml: - 'pypy-3.8'
2 .github/workflows/ci.yml: python: '3.8'
1 .github/workflows/ci.yml: - python: '3.8'
1 .github/workflows/ci.yml: - python: 3.8
1 .github/workflows/ci.yml: python: 'pypy-3.8'
1 .github/workflows/configure.yml: cmake: "3.8"
1 .github/workflows/configure.yml: name: 🐍 3.8 • CMake ${{ matrix.cmake }} • ${{ matrix.runs-on }}
1 .github/workflows/configure.yml: - name: Setup Python 3.8
1 .github/workflows/configure.yml: python-version: 3.8
1 .github/workflows/pip.yml: name: 🐍 3.8 • 📦 & 📦 tests • ubuntu-latest
1 .github/workflows/pip.yml: name: 🐍 3.8 • 📦 tests • windows-latest
2 .github/workflows/pip.yml: - name: Setup 🐍 3.8
2 .github/workflows/pip.yml: python-version: 3.8
2 include/pybind11/cast.h:#if !defined(PYPY_VERSION)
2 include/pybind11/cast.h:#if defined(PYPY_VERSION)
2 include/pybind11/cast.h: // PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
5 include/pybind11/detail/class.h:#if !defined(PYPY_VERSION)
1 include/pybind11/detail/class.h:#if defined(PYPY_VERSION)
1 include/pybind11/detail/class.h: // This was not needed before Python 3.8 (Python issue 35810)
1 include/pybind11/detail/common.h: && !defined(PYPY_VERSION) && !defined(PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF)
2 include/pybind11/detail/common.h:# error "PYTHON < 3.8 IS UNSUPPORTED. pybind11 v2.13 was the last to support Python 3.7."
1 include/pybind11/detail/common.h:#if defined(PYPY_VERSION) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
1 include/pybind11/detail/common.h:#if PY_VERSION_HEX < 0x03080000
1 include/pybind11/detail/common.h: = PYBIND11_TOSTRING(PY_MAJOR_VERSION) "." PYBIND11_TOSTRING(PY_MINOR_VERSION); \
1 include/pybind11/detail/internals.h: // called. PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does
1 include/pybind11/detail/internals.h:#if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION)
1 include/pybind11/detail/internals.h:// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
1 include/pybind11/detail/type_caster_base.h:#if defined(PYPY_VERSION)
1 include/pybind11/embed.h:# define PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX (0x03080000)
1 include/pybind11/embed.h:#if defined(PYPY_VERSION)
1 include/pybind11/eval.h: // globals if not yet present. Python 3.8 made PyRun_String behave
2 include/pybind11/eval.h:#if defined(PYPY_VERSION)
2 include/pybind11/eval.h: // was missing from PyPy3.8 7.3.7.
2 include/pybind11/gil.h: /// allowed during shutdown. Check _Py_IsFinalizing() on Python 3.7+, and
1 include/pybind11/pybind11.h:#if !defined(PYPY_VERSION)
4 include/pybind11/pybind11.h:#if !defined(PYPY_VERSION) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 9
1 include/pybind11/pytypes.h:#endif //! defined(PYPY_VERSION)
2 include/pybind11/pytypes.h:#if !defined(PYPY_VERSION)
1 include/pybind11/pytypes.h:# if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x07030a00
1 include/pybind11/pytypes.h:#ifdef PYPY_VERSION
1 include/pybind11/stl/filesystem.h:# if !defined(PYPY_VERSION)
2 pybind11/__init__.py:if sys.version_info < (3, 8):
2 pybind11/__init__.py: msg = "pybind11 does not support Python < 3.8. v2.13 was the last release supporting Python 3.7."
1 pyproject.toml:master.py-version = "3.8"
1 pyproject.toml:python_version = "3.8"
1 README.rst:lines of code and depend on Python (3.8+, or PyPy) and the C++
2 README.rst:- Python 3.8+, and PyPy3 7.3 are supported with an implementation-agnostic
1 setup.cfg: Programming Language :: Python :: 3.8
1 setup.cfg:python_requires = >=3.8
1 setup.py:# TODO: use literals & overload (typing extensions or Python 3.8)
1 tests/CMakeLists.txt:if(NOT CMAKE_VERSION VERSION_LESS 3.8)
2 tests/constructor_stats.h:#if defined(PYPY_VERSION)
1 tests/env.py: doesn't work on CPython 3.8.0 with pytest==3.3.2 on Ubuntu 18.04 (#2922).
1 tests/requirements.txt:build~=1.0; python_version>="3.8"
1 tests/requirements.txt:numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.8" and python_version<"3.10"
1 tests/requirements.txt:numpy~=1.23.0; python_version=="3.8" and platform_python_implementation=="PyPy"
1 tests/test_buffers.py: env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
1 tests/test_builtin_casters.py: # Before Python 3.8, `PyLong_AsLong` does not pick up on `obj.__index__`,
2 tests/test_builtin_casters.py: if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
4 tests/test_builtin_casters.py: # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
1 tests/test_callbacks.py: assert m.test_callback3(z.double) == "func(43) = 86"
2 tests/test_call_policies.cpp:#if !defined(PYPY_VERSION)
1 tests/test_chrono.py: diff = m.test_chrono_float_diff(43.789012, 1.123456)
1 tests/test_constants_and_functions.py: assert m.f3(86) == 89
1 tests/test_eigen_matrix.py: a_copy3[8, 1] = 11
1 tests/test_eigen_matrix.py: assert np.all(cornersc == np.array([[1.0, 3], [7, 9]]))
1 tests/test_eigen_matrix.py: assert np.all(cornersr == np.array([[1.0, 3], [7, 9]]))
1 tests/test_eigen_matrix.py: mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
1 tests/test_exceptions.py: if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6
2 tests/test_exceptions.py:@pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False)
1 tests/test_factory_constructors.py: assert [i.alive() for i in cstats] == [13, 7]
1 tests/test_kwargs_and_defaults.cpp:#ifdef PYPY_VERSION
1 tests/test_local_bindings.py: assert i1.get3() == 8
1 tests/test_methods_and_attributes.cpp:#if !defined(PYPY_VERSION)
1 tests/test_numpy_array.py: a = np.arange(3 * 7 * 2) + 1
1 tests/test_numpy_array.py: assert str(excinfo.value) == "cannot reshape array of size 42 into shape (3,7,1)"
2 tests/test_numpy_array.py: assert x.shape == (3, 7, 2)
2 tests/test_numpy_array.py: m.reshape_tuple(a, (3, 7, 1))
2 tests/test_numpy_array.py: x = m.reshape_tuple(a, (3, 7, 2))
1 tests/test_numpy_vectorize.py: assert np.isclose(m.vectorized_func3(np.array(3 + 7j)), [6 + 14j])
1 tests/test_pickling.cpp:#if !defined(PYPY_VERSION)
1 tests/test_pytypes.cpp:#if (defined(__APPLE__) && defined(__clang__)) || defined(PYPY_VERSION)
1 tests/test_smart_ptr.cpp: m.def("make_myobject3_1", []() { return new MyObject3(8); });
1 tests/test_smart_ptr.py: assert cstats.values() == ["MyObject3[9]", "MyObject3[8]", "MyObject3[9]"]
1 tests/test_stl_binders.py: assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 88])
1 tests/test_stl_binders.py: assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 88, 4])
1 tests/test_type_caster_pyobject_ptr.cpp:#if !defined(PYPY_VERSION) // It is not worth the trouble doing something special for PyPy.
1 tools/FindPythonLibsNew.cmake: set(PythonLibsNew_FIND_VERSION "3.8")
1 tools/JoinPaths.cmake:# https://docs.python.org/3.7/library/os.path.html#os.path.join
1 tools/pybind11NewTools.cmake: Python 3.8 REQUIRED COMPONENTS ${_pybind11_interp_component} ${_pybind11_dev_component}
1 tools/pybind11NewTools.cmake:# Python debug libraries expose slightly different objects before 3.8
1 tools/pybind11Tools.cmake: "3.12;3.11;3.10;3.9;3.8"
1 tools/pybind11Tools.cmake: if(NOT DEFINED PYPY_VERSION)
1 tools/pybind11Tools.cmake: message(STATUS "PYPY ${PYPY_VERSION} (Py ${PYTHON_VERSION})")
1 tools/pybind11Tools.cmake:# Python debug libraries expose slightly different objects before 3.8
1 tools/pybind11Tools.cmake: set(PYPY_VERSION
```
* Change `[tool.ruff]` `target-version` to `"py38"`, as suggested by @Skylion007
2024-07-30 16:18:35 +00:00
|
|
|
#if defined(PYPY_VERSION)
|
2021-01-25 20:05:17 +00:00
|
|
|
object index;
|
2022-02-10 20:17:07 +00:00
|
|
|
if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr())
|
2021-01-25 20:05:17 +00:00
|
|
|
index = reinterpret_steal<object>(PyNumber_Index(src.ptr()));
|
|
|
|
if (!index) {
|
|
|
|
PyErr_Clear();
|
|
|
|
if (!convert)
|
|
|
|
return false;
|
2022-02-10 20:17:07 +00:00
|
|
|
} else {
|
2021-01-25 20:05:17 +00:00
|
|
|
src_or_index = index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (std::is_unsigned<py_type>::value) {
|
|
|
|
py_value = as_unsigned<py_type>(src_or_index.ptr());
|
|
|
|
} else { // signed integer:
|
|
|
|
py_value = sizeof(T) <= sizeof(long)
|
2022-02-10 20:17:07 +00:00
|
|
|
? (py_type) PyLong_AsLong(src_or_index.ptr())
|
|
|
|
: (py_type) PYBIND11_LONG_AS_LONGLONG(src_or_index.ptr());
|
2021-01-25 20:05:17 +00:00
|
|
|
}
|
2015-11-30 11:30:28 +00:00
|
|
|
}
|
|
|
|
|
2020-09-10 15:49:26 +00:00
|
|
|
// Python API reported an error
|
Fix unsigned error value casting
When casting to an unsigned type from a python 2 `int`, we currently
cast using `(unsigned long long) PyLong_AsUnsignedLong(src.ptr())`.
If the Python cast fails, it returns (unsigned long) -1, but then we
cast this to `unsigned long long`, which means we get 4294967295, but
because that isn't equal to `(unsigned long long) -1`, we don't detect
the failure.
This commit moves the unsigned casting into a `detail::as_unsigned`
function which, upon error, casts -1 to the final type, and otherwise
casts the return value to the final type to avoid the problematic double
cast when an error occurs.
The error most commonly shows up wherever `long` is 32-bits (e.g. under
both 32- and 64-bit Windows, and under 32-bit linux) when passing a
negative value to a bound function taking an `unsigned long`.
Fixes #929.
The added tests also trigger a latent segfault under PyPy: when casting
to an integer smaller than `long` (e.g. casting to a `uint32_t` on a
64-bit `long` architecture) we check both for a Python error and also
that the resulting intermediate value will fit in the final type. If
there is no conversion error, but we get a value that would overflow, we
end up calling `PyErr_ExceptionMatches()` illegally: that call is only
allowed when there is a current exception. Under PyPy, this segfaults
the test suite. It doesn't appear to segfault under CPython, but the
documentation suggests that it *could* do so. The fix is to only check
for the exception match if we actually got an error.
2017-07-01 20:31:49 +00:00
|
|
|
bool py_err = py_value == (py_type) -1 && PyErr_Occurred();
|
2019-07-18 07:01:50 +00:00
|
|
|
|
2020-09-10 15:49:26 +00:00
|
|
|
// Check to see if the conversion is valid (integers should match exactly)
|
|
|
|
// Signed/unsigned checks happen elsewhere
|
2022-02-10 20:17:07 +00:00
|
|
|
if (py_err
|
|
|
|
|| (std::is_integral<T>::value && sizeof(py_type) != sizeof(T)
|
|
|
|
&& py_value != (py_type) (T) py_value)) {
|
2015-11-30 11:30:28 +00:00
|
|
|
PyErr_Clear();
|
2021-07-27 22:32:26 +00:00
|
|
|
if (py_err && convert && (PyNumber_Check(src.ptr()) != 0)) {
|
2017-09-10 14:53:02 +00:00
|
|
|
auto tmp = reinterpret_steal<object>(std::is_floating_point<T>::value
|
2022-02-10 20:17:07 +00:00
|
|
|
? PyNumber_Float(src.ptr())
|
|
|
|
: PyNumber_Long(src.ptr()));
|
2016-11-07 14:59:01 +00:00
|
|
|
PyErr_Clear();
|
|
|
|
return load(tmp, false);
|
|
|
|
}
|
2015-11-30 11:30:28 +00:00
|
|
|
return false;
|
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2015-11-30 11:30:28 +00:00
|
|
|
value = (T) py_value;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename U = T>
|
2018-07-17 13:48:51 +00:00
|
|
|
static typename std::enable_if<std::is_floating_point<U>::value, handle>::type
|
|
|
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
|
|
|
return PyFloat_FromDouble((double) src);
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename U = T>
|
|
|
|
static typename std::enable_if<!std::is_floating_point<U>::value && std::is_signed<U>::value
|
|
|
|
&& (sizeof(U) <= sizeof(long)),
|
|
|
|
handle>::type
|
2018-07-17 13:48:51 +00:00
|
|
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
|
|
|
return PYBIND11_LONG_FROM_SIGNED((long) src);
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename U = T>
|
|
|
|
static typename std::enable_if<!std::is_floating_point<U>::value && std::is_unsigned<U>::value
|
|
|
|
&& (sizeof(U) <= sizeof(unsigned long)),
|
|
|
|
handle>::type
|
2018-07-17 13:48:51 +00:00
|
|
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
|
|
|
return PYBIND11_LONG_FROM_UNSIGNED((unsigned long) src);
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename U = T>
|
|
|
|
static typename std::enable_if<!std::is_floating_point<U>::value && std::is_signed<U>::value
|
|
|
|
&& (sizeof(U) > sizeof(long)),
|
|
|
|
handle>::type
|
2018-07-17 13:48:51 +00:00
|
|
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
|
|
|
return PyLong_FromLongLong((long long) src);
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename U = T>
|
|
|
|
static typename std::enable_if<!std::is_floating_point<U>::value && std::is_unsigned<U>::value
|
|
|
|
&& (sizeof(U) > sizeof(unsigned long)),
|
|
|
|
handle>::type
|
2018-07-17 13:48:51 +00:00
|
|
|
cast(U src, return_value_policy /* policy */, handle /* parent */) {
|
|
|
|
return PyLong_FromUnsignedLongLong((unsigned long long) src);
|
2015-11-30 11:30:28 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 19:24:21 +00:00
|
|
|
PYBIND11_TYPE_CASTER(T, const_name<std::is_integral<T>::value>("int", "float"));
|
2015-11-30 11:30:28 +00:00
|
|
|
};
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
struct void_caster {
|
2015-07-05 18:05:44 +00:00
|
|
|
public:
|
2017-05-09 21:30:05 +00:00
|
|
|
bool load(handle src, bool) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (src && src.is_none()) {
|
2017-05-09 21:30:05 +00:00
|
|
|
return true;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2017-05-09 21:30:05 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-11-15 12:00:38 +00:00
|
|
|
static handle cast(T, return_value_policy /* policy */, handle /* parent */) {
|
2022-10-21 16:51:26 +00:00
|
|
|
return none().release();
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
2021-12-21 19:24:21 +00:00
|
|
|
PYBIND11_TYPE_CASTER(T, const_name("None"));
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <>
|
|
|
|
class type_caster<void_type> : public void_caster<void_type> {};
|
2016-11-15 12:00:38 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <>
|
|
|
|
class type_caster<void> : public type_caster<void_type> {
|
2016-03-26 16:51:09 +00:00
|
|
|
public:
|
|
|
|
using type_caster<void_type>::cast;
|
|
|
|
|
|
|
|
bool load(handle h, bool) {
|
2016-05-10 14:59:01 +00:00
|
|
|
if (!h) {
|
|
|
|
return false;
|
2021-07-09 13:45:53 +00:00
|
|
|
}
|
|
|
|
if (h.is_none()) {
|
2016-03-26 19:41:28 +00:00
|
|
|
value = nullptr;
|
|
|
|
return true;
|
|
|
|
}
|
2016-04-30 17:56:10 +00:00
|
|
|
|
|
|
|
/* Check if this is a capsule */
|
2016-10-23 12:50:08 +00:00
|
|
|
if (isinstance<capsule>(h)) {
|
2016-10-28 01:08:15 +00:00
|
|
|
value = reinterpret_borrow<capsule>(h);
|
2016-04-30 17:56:10 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if this is a C++ type */
|
2022-02-09 14:24:57 +00:00
|
|
|
const auto &bases = all_type_info((PyTypeObject *) type::handle_of(h).ptr());
|
2017-02-23 02:36:09 +00:00
|
|
|
if (bases.size() == 1) { // Only allowing loading from a single-value type
|
|
|
|
value = values_and_holders(reinterpret_cast<instance *>(h.ptr())).begin()->value_ptr();
|
2016-04-30 17:56:10 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fail */
|
|
|
|
return false;
|
2016-03-26 16:51:09 +00:00
|
|
|
}
|
|
|
|
|
2016-04-30 17:13:18 +00:00
|
|
|
static handle cast(const void *ptr, return_value_policy /* policy */, handle /* parent */) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (ptr) {
|
2016-03-26 19:41:28 +00:00
|
|
|
return capsule(ptr).release();
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2022-10-21 16:51:26 +00:00
|
|
|
return none().release();
|
2016-03-26 16:51:09 +00:00
|
|
|
}
|
2016-03-26 19:41:28 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
using cast_op_type = void *&;
|
CodeHealth: Enabling clang-tidy google-explicit-constructor (#3250)
* Adding google-explicit-constructor to .clang-tidy
* clang-tidy explicit attr.h (all automatic)
* clang-tidy explicit cast.h (all automatic)
* clang-tidy detail/init.h (1 NOLINT)
* clang-tidy detail/type_caster_base.h (2 NOLINT)
* clang-tidy pybind11.h (7 NOLINT)
* clang-tidy detail/common.h (3 NOLINT)
* clang-tidy detail/descr.h (2 NOLINT)
* clang-tidy pytypes.h (23 NOLINT, only 1 explicit)
* clang-tidy eigen.h (7 NOLINT, 0 explicit)
* Adding 2 explicit in functional.h
* Adding 4 explicit in iostream.h
* clang-tidy numpy.h (1 NOLINT, 1 explicit)
* clang-tidy embed.h (0 NOLINT, 1 explicit)
* clang-tidy tests/local_bindings.h (0 NOLINT, 4 explicit)
* clang-tidy tests/pybind11_cross_module_tests.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/pybind11_tests.h (0 NOLINT, 2 explicit)
* clang-tidy tests/test_buffers.cpp (0 NOLINT, 2 explicit)
* clang-tidy tests/test_builtin_casters.cpp (0 NOLINT, 4 explicit)
* clang-tidy tests/test_class.cpp (0 NOLINT, 6 explicit)
* clang-tidy tests/test_copy_move.cpp (0 NOLINT, 7 explicit)
* clang-tidy tests/test_embed/external_module.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/test_embed/test_interpreter.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/object.h (0 NOLINT, 2 explicit)
* clang-tidy batch of fully automatic fixes.
* Workaround for MSVC 19.16.27045.0 C++17 Python 2 C++ syntax error.
2021-09-09 01:53:38 +00:00
|
|
|
explicit operator void *&() { return value; }
|
2021-12-21 19:24:21 +00:00
|
|
|
static constexpr auto name = const_name("capsule");
|
2022-02-10 20:17:07 +00:00
|
|
|
|
2016-03-26 16:51:09 +00:00
|
|
|
private:
|
2016-03-26 22:04:10 +00:00
|
|
|
void *value = nullptr;
|
2016-03-26 16:51:09 +00:00
|
|
|
};
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <>
|
|
|
|
class type_caster<std::nullptr_t> : public void_caster<std::nullptr_t> {};
|
2015-10-01 16:37:26 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <>
|
|
|
|
class type_caster<bool> {
|
2015-07-05 18:05:44 +00:00
|
|
|
public:
|
2017-07-23 15:02:43 +00:00
|
|
|
bool load(handle src, bool convert) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!src) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-07-09 13:45:53 +00:00
|
|
|
if (src.ptr() == Py_True) {
|
|
|
|
value = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (src.ptr() == Py_False) {
|
|
|
|
value = false;
|
|
|
|
return true;
|
|
|
|
}
|
2024-03-26 22:20:11 +00:00
|
|
|
if (convert || is_numpy_bool(src)) {
|
|
|
|
// (allow non-implicit conversion for numpy booleans), use strncmp
|
|
|
|
// since NumPy 1.x had an additional trailing underscore.
|
2017-07-23 15:02:43 +00:00
|
|
|
|
|
|
|
Py_ssize_t res = -1;
|
|
|
|
if (src.is_none()) {
|
2022-02-10 20:17:07 +00:00
|
|
|
res = 0; // None is implicitly converted to False
|
2017-07-23 15:02:43 +00:00
|
|
|
}
|
2022-02-10 20:17:07 +00:00
|
|
|
#if defined(PYPY_VERSION)
|
2022-02-11 02:28:08 +00:00
|
|
|
// On PyPy, check that "__bool__" attr exists
|
2017-07-23 15:02:43 +00:00
|
|
|
else if (hasattr(src, PYBIND11_BOOL_ATTR)) {
|
|
|
|
res = PyObject_IsTrue(src.ptr());
|
|
|
|
}
|
2022-02-10 20:17:07 +00:00
|
|
|
#else
|
2017-07-23 15:02:43 +00:00
|
|
|
// Alternate approach for CPython: this does the same as the above, but optimized
|
|
|
|
// using the CPython API so as to avoid an unneeded attribute lookup.
|
2022-02-09 14:24:57 +00:00
|
|
|
else if (auto *tp_as_number = src.ptr()->ob_type->tp_as_number) {
|
2017-07-23 15:02:43 +00:00
|
|
|
if (PYBIND11_NB_BOOL(tp_as_number)) {
|
|
|
|
res = (*PYBIND11_NB_BOOL(tp_as_number))(src.ptr());
|
|
|
|
}
|
|
|
|
}
|
2022-02-10 20:17:07 +00:00
|
|
|
#endif
|
2017-07-23 15:02:43 +00:00
|
|
|
if (res == 0 || res == 1) {
|
2021-07-26 20:26:36 +00:00
|
|
|
value = (res != 0);
|
2017-07-23 15:02:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
2021-07-09 13:45:53 +00:00
|
|
|
PyErr_Clear();
|
2017-07-23 15:02:43 +00:00
|
|
|
}
|
|
|
|
return false;
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
static handle cast(bool src, return_value_policy /* policy */, handle /* parent */) {
|
|
|
|
return handle(src ? Py_True : Py_False).inc_ref();
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
2021-12-21 19:24:21 +00:00
|
|
|
PYBIND11_TYPE_CASTER(bool, const_name("bool"));
|
2024-03-26 22:20:11 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
// Test if an object is a NumPy boolean (without fetching the type).
|
|
|
|
static inline bool is_numpy_bool(handle object) {
|
|
|
|
const char *type_name = Py_TYPE(object.ptr())->tp_name;
|
|
|
|
// Name changed to `numpy.bool` in NumPy 2, `numpy.bool_` is needed for 1.x support
|
|
|
|
return std::strcmp("numpy.bool", type_name) == 0
|
|
|
|
|| std::strcmp("numpy.bool_", type_name) == 0;
|
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
// Helper class for UTF-{8,16,32} C++ stl strings:
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename StringType, bool IsView = false>
|
|
|
|
struct string_caster {
|
2017-06-19 00:32:22 +00:00
|
|
|
using CharT = typename StringType::value_type;
|
|
|
|
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
// Simplify life by being able to assume standard char sizes (the standard only guarantees
|
2017-06-19 00:32:22 +00:00
|
|
|
// minimums, but Python requires exact sizes)
|
2022-02-10 20:17:07 +00:00
|
|
|
static_assert(!std::is_same<CharT, char>::value || sizeof(CharT) == 1,
|
|
|
|
"Unsupported char size != 1");
|
2019-12-19 11:16:24 +00:00
|
|
|
#if defined(PYBIND11_HAS_U8STRING)
|
2022-02-10 20:17:07 +00:00
|
|
|
static_assert(!std::is_same<CharT, char8_t>::value || sizeof(CharT) == 1,
|
|
|
|
"Unsupported char8_t size != 1");
|
2019-12-19 11:16:24 +00:00
|
|
|
#endif
|
2022-02-10 20:17:07 +00:00
|
|
|
static_assert(!std::is_same<CharT, char16_t>::value || sizeof(CharT) == 2,
|
|
|
|
"Unsupported char16_t size != 2");
|
|
|
|
static_assert(!std::is_same<CharT, char32_t>::value || sizeof(CharT) == 4,
|
|
|
|
"Unsupported char32_t size != 4");
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
// wchar_t can be either 16 bits (Windows) or 32 (everywhere else)
|
|
|
|
static_assert(!std::is_same<CharT, wchar_t>::value || sizeof(CharT) == 2 || sizeof(CharT) == 4,
|
2022-02-10 20:17:07 +00:00
|
|
|
"Unsupported wchar_t size != 2/4");
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
static constexpr size_t UTF_N = 8 * sizeof(CharT);
|
|
|
|
|
2016-03-26 22:38:46 +00:00
|
|
|
bool load(handle src, bool) {
|
|
|
|
handle load_src = src;
|
2016-05-10 14:59:01 +00:00
|
|
|
if (!src) {
|
|
|
|
return false;
|
2021-07-09 13:45:53 +00:00
|
|
|
}
|
|
|
|
if (!PyUnicode_Check(load_src.ptr())) {
|
2022-02-23 23:21:03 +00:00
|
|
|
return load_raw(load_src);
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
}
|
|
|
|
|
2022-02-11 02:28:08 +00:00
|
|
|
// For UTF-8 we avoid the need for a temporary `bytes` object by using
|
|
|
|
// `PyUnicode_AsUTF8AndSize`.
|
2022-11-28 15:39:38 +00:00
|
|
|
if (UTF_N == 8) {
|
2021-09-09 19:56:10 +00:00
|
|
|
Py_ssize_t size = -1;
|
|
|
|
const auto *buffer
|
|
|
|
= reinterpret_cast<const CharT *>(PyUnicode_AsUTF8AndSize(load_src.ptr(), &size));
|
|
|
|
if (!buffer) {
|
|
|
|
PyErr_Clear();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
value = StringType(buffer, static_cast<size_t>(size));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
auto utfNbytes
|
|
|
|
= reinterpret_steal<object>(PyUnicode_AsEncodedString(load_src.ptr(),
|
|
|
|
UTF_N == 8 ? "utf-8"
|
|
|
|
: UTF_N == 16 ? "utf-16"
|
|
|
|
: "utf-32",
|
|
|
|
nullptr));
|
|
|
|
if (!utfNbytes) {
|
|
|
|
PyErr_Clear();
|
|
|
|
return false;
|
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
const auto *buffer
|
|
|
|
= reinterpret_cast<const CharT *>(PYBIND11_BYTES_AS_STRING(utfNbytes.ptr()));
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
size_t length = (size_t) PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT);
|
2021-07-30 18:25:29 +00:00
|
|
|
// Skip BOM for UTF-16/32
|
2022-11-28 15:39:38 +00:00
|
|
|
if (UTF_N > 8) {
|
2021-07-30 18:25:29 +00:00
|
|
|
buffer++;
|
|
|
|
length--;
|
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
value = StringType(buffer, length);
|
2017-06-19 00:32:22 +00:00
|
|
|
|
|
|
|
// If we're loading a string_view we need to keep the encoded Python object alive:
|
2022-02-08 00:23:20 +00:00
|
|
|
if (IsView) {
|
2017-06-26 18:34:06 +00:00
|
|
|
loader_life_support::add_patient(utfNbytes);
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2017-06-19 00:32:22 +00:00
|
|
|
|
2016-03-26 22:38:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
2016-03-02 05:59:39 +00:00
|
|
|
|
2024-06-11 02:19:37 +00:00
|
|
|
static handle
|
|
|
|
cast(const StringType &src, return_value_policy /* policy */, handle /* parent */) {
|
2017-06-19 00:32:22 +00:00
|
|
|
const char *buffer = reinterpret_cast<const char *>(src.data());
|
2020-09-11 03:20:47 +00:00
|
|
|
auto nbytes = ssize_t(src.size() * sizeof(CharT));
|
2024-06-11 02:19:37 +00:00
|
|
|
handle s = decode_utfN(buffer, nbytes);
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!s) {
|
|
|
|
throw error_already_set();
|
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
return s;
|
2016-03-26 22:38:46 +00:00
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2021-12-21 19:24:21 +00:00
|
|
|
PYBIND11_TYPE_CASTER(StringType, const_name(PYBIND11_STRING_NAME));
|
Call PyUnicode_DecodeUTF* directly
Some versions of Python 2.7 reportedly (#713) have issues with
PyUnicode_Decode being passed the encoding string, so just skip it
entirely by calling the PyUnicode_DecodeUTF* function directly. This
will also be slightly more efficient by avoiding having to check the
encoding string, and (for python 2) going through the unicode class's
decode (python 3 fast-tracks this for all utf-{8,16,32} encodings;
python 2 only fast-tracked for the exact string "utf-8", which we
weren't passing anyway (we had "utf8")).
This doesn't work for PyPy, however: its `PyUnicode_DecodeUTF{8,16,32}`
appear rather broken: the UTF8 one segfaults, while the 16/32 require
recasting into a non-const `char *` (and might segfault; I didn't get
far enough to find out). Just avoid the whole thing by keeping the
encoding-passed-as-string version for PyPy, which seems to work
reliably.
2017-03-09 16:35:28 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
static handle decode_utfN(const char *buffer, ssize_t nbytes) {
|
|
|
|
#if !defined(PYPY_VERSION)
|
2022-02-10 20:17:07 +00:00
|
|
|
return UTF_N == 8 ? PyUnicode_DecodeUTF8(buffer, nbytes, nullptr)
|
|
|
|
: UTF_N == 16 ? PyUnicode_DecodeUTF16(buffer, nbytes, nullptr, nullptr)
|
|
|
|
: PyUnicode_DecodeUTF32(buffer, nbytes, nullptr, nullptr);
|
Call PyUnicode_DecodeUTF* directly
Some versions of Python 2.7 reportedly (#713) have issues with
PyUnicode_Decode being passed the encoding string, so just skip it
entirely by calling the PyUnicode_DecodeUTF* function directly. This
will also be slightly more efficient by avoiding having to check the
encoding string, and (for python 2) going through the unicode class's
decode (python 3 fast-tracks this for all utf-{8,16,32} encodings;
python 2 only fast-tracked for the exact string "utf-8", which we
weren't passing anyway (we had "utf8")).
This doesn't work for PyPy, however: its `PyUnicode_DecodeUTF{8,16,32}`
appear rather broken: the UTF8 one segfaults, while the 16/32 require
recasting into a non-const `char *` (and might segfault; I didn't get
far enough to find out). Just avoid the whole thing by keeping the
encoding-passed-as-string version for PyPy, which seems to work
reliably.
2017-03-09 16:35:28 +00:00
|
|
|
#else
|
2022-02-10 20:17:07 +00:00
|
|
|
// PyPy segfaults when on PyUnicode_DecodeUTF16 (and possibly on PyUnicode_DecodeUTF32 as
|
|
|
|
// well), so bypass the whole thing by just passing the encoding as a string value, which
|
|
|
|
// works properly:
|
|
|
|
return PyUnicode_Decode(buffer,
|
|
|
|
nbytes,
|
|
|
|
UTF_N == 8 ? "utf-8"
|
|
|
|
: UTF_N == 16 ? "utf-16"
|
|
|
|
: "utf-32",
|
|
|
|
nullptr);
|
Call PyUnicode_DecodeUTF* directly
Some versions of Python 2.7 reportedly (#713) have issues with
PyUnicode_Decode being passed the encoding string, so just skip it
entirely by calling the PyUnicode_DecodeUTF* function directly. This
will also be slightly more efficient by avoiding having to check the
encoding string, and (for python 2) going through the unicode class's
decode (python 3 fast-tracks this for all utf-{8,16,32} encodings;
python 2 only fast-tracked for the exact string "utf-8", which we
weren't passing anyway (we had "utf8")).
This doesn't work for PyPy, however: its `PyUnicode_DecodeUTF{8,16,32}`
appear rather broken: the UTF8 one segfaults, while the 16/32 require
recasting into a non-const `char *` (and might segfault; I didn't get
far enough to find out). Just avoid the whole thing by keeping the
encoding-passed-as-string version for PyPy, which seems to work
reliably.
2017-03-09 16:35:28 +00:00
|
|
|
#endif
|
|
|
|
}
|
2017-04-26 14:49:55 +00:00
|
|
|
|
2022-02-23 23:21:03 +00:00
|
|
|
// When loading into a std::string or char*, accept a bytes/bytearray object as-is (i.e.
|
2017-06-06 19:31:41 +00:00
|
|
|
// without any encoding/decoding attempt). For other C++ char sizes this is a no-op.
|
2017-04-26 14:49:55 +00:00
|
|
|
// which supports loading a unicode from a str, doesn't take this path.
|
|
|
|
template <typename C = CharT>
|
2022-02-23 23:21:03 +00:00
|
|
|
bool load_raw(enable_if_t<std::is_same<C, char>::value, handle> src) {
|
2017-04-26 14:49:55 +00:00
|
|
|
if (PYBIND11_BYTES_CHECK(src.ptr())) {
|
2022-02-11 02:28:08 +00:00
|
|
|
// We were passed raw bytes; accept it into a std::string or char*
|
2017-04-26 14:49:55 +00:00
|
|
|
// without any encoding attempt.
|
|
|
|
const char *bytes = PYBIND11_BYTES_AS_STRING(src.ptr());
|
2022-02-23 23:21:03 +00:00
|
|
|
if (!bytes) {
|
|
|
|
pybind11_fail("Unexpected PYBIND11_BYTES_AS_STRING() failure.");
|
|
|
|
}
|
|
|
|
value = StringType(bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr()));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (PyByteArray_Check(src.ptr())) {
|
|
|
|
// We were passed a bytearray; accept it into a std::string or char*
|
|
|
|
// without any encoding attempt.
|
|
|
|
const char *bytearray = PyByteArray_AsString(src.ptr());
|
|
|
|
if (!bytearray) {
|
|
|
|
pybind11_fail("Unexpected PyByteArray_AsString() failure.");
|
2017-04-26 14:49:55 +00:00
|
|
|
}
|
2022-02-23 23:21:03 +00:00
|
|
|
value = StringType(bytearray, (size_t) PyByteArray_Size(src.ptr()));
|
|
|
|
return true;
|
2017-04-26 14:49:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2017-06-06 19:31:41 +00:00
|
|
|
|
2017-04-26 14:49:55 +00:00
|
|
|
template <typename C = CharT>
|
2022-02-23 23:21:03 +00:00
|
|
|
bool load_raw(enable_if_t<!std::is_same<C, char>::value, handle>) {
|
2022-02-10 20:17:07 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-03-02 05:59:39 +00:00
|
|
|
};
|
|
|
|
|
2017-06-19 00:32:22 +00:00
|
|
|
template <typename CharT, class Traits, class Allocator>
|
2022-02-10 20:17:07 +00:00
|
|
|
struct type_caster<std::basic_string<CharT, Traits, Allocator>,
|
|
|
|
enable_if_t<is_std_char_type<CharT>::value>>
|
2017-06-19 00:32:22 +00:00
|
|
|
: string_caster<std::basic_string<CharT, Traits, Allocator>> {};
|
|
|
|
|
|
|
|
#ifdef PYBIND11_HAS_STRING_VIEW
|
|
|
|
template <typename CharT, class Traits>
|
2022-02-10 20:17:07 +00:00
|
|
|
struct type_caster<std::basic_string_view<CharT, Traits>,
|
|
|
|
enable_if_t<is_std_char_type<CharT>::value>>
|
2017-06-19 00:32:22 +00:00
|
|
|
: string_caster<std::basic_string_view<CharT, Traits>, true> {};
|
|
|
|
#endif
|
|
|
|
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
// Type caster for C-style strings. We basically use a std::string type caster, but also add the
|
|
|
|
// ability to use None as a nullptr char* (which the string caster doesn't allow).
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename CharT>
|
|
|
|
struct type_caster<CharT, enable_if_t<is_std_char_type<CharT>::value>> {
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
using StringType = std::basic_string<CharT>;
|
2022-04-11 17:36:24 +00:00
|
|
|
using StringCaster = make_caster<StringType>;
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
StringCaster str_caster;
|
|
|
|
bool none = false;
|
2017-10-06 14:50:10 +00:00
|
|
|
CharT one_char = 0;
|
2022-02-10 20:17:07 +00:00
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
public:
|
2016-03-26 22:38:46 +00:00
|
|
|
bool load(handle src, bool convert) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!src) {
|
|
|
|
return false;
|
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
if (src.is_none()) {
|
|
|
|
// Defer accepting None to other overloads (if we aren't in convert mode):
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!convert) {
|
|
|
|
return false;
|
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
none = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return str_caster.load(src, convert);
|
2016-03-26 22:37:51 +00:00
|
|
|
}
|
|
|
|
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
static handle cast(const CharT *src, return_value_policy policy, handle parent) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (src == nullptr) {
|
2022-10-21 16:51:26 +00:00
|
|
|
return pybind11::none().release();
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
return StringCaster::cast(StringType(src), policy, parent);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
static handle cast(CharT src, return_value_policy policy, handle parent) {
|
|
|
|
if (std::is_same<char, CharT>::value) {
|
|
|
|
handle s = PyUnicode_DecodeLatin1((const char *) &src, 1, nullptr);
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!s) {
|
|
|
|
throw error_already_set();
|
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return StringCaster::cast(StringType(1, src), policy, parent);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
CodeHealth: Enabling clang-tidy google-explicit-constructor (#3250)
* Adding google-explicit-constructor to .clang-tidy
* clang-tidy explicit attr.h (all automatic)
* clang-tidy explicit cast.h (all automatic)
* clang-tidy detail/init.h (1 NOLINT)
* clang-tidy detail/type_caster_base.h (2 NOLINT)
* clang-tidy pybind11.h (7 NOLINT)
* clang-tidy detail/common.h (3 NOLINT)
* clang-tidy detail/descr.h (2 NOLINT)
* clang-tidy pytypes.h (23 NOLINT, only 1 explicit)
* clang-tidy eigen.h (7 NOLINT, 0 explicit)
* Adding 2 explicit in functional.h
* Adding 4 explicit in iostream.h
* clang-tidy numpy.h (1 NOLINT, 1 explicit)
* clang-tidy embed.h (0 NOLINT, 1 explicit)
* clang-tidy tests/local_bindings.h (0 NOLINT, 4 explicit)
* clang-tidy tests/pybind11_cross_module_tests.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/pybind11_tests.h (0 NOLINT, 2 explicit)
* clang-tidy tests/test_buffers.cpp (0 NOLINT, 2 explicit)
* clang-tidy tests/test_builtin_casters.cpp (0 NOLINT, 4 explicit)
* clang-tidy tests/test_class.cpp (0 NOLINT, 6 explicit)
* clang-tidy tests/test_copy_move.cpp (0 NOLINT, 7 explicit)
* clang-tidy tests/test_embed/external_module.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/test_embed/test_interpreter.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/object.h (0 NOLINT, 2 explicit)
* clang-tidy batch of fully automatic fixes.
* Workaround for MSVC 19.16.27045.0 C++17 Python 2 C++ syntax error.
2021-09-09 01:53:38 +00:00
|
|
|
explicit operator CharT *() {
|
|
|
|
return none ? nullptr : const_cast<CharT *>(static_cast<StringType &>(str_caster).c_str());
|
|
|
|
}
|
|
|
|
explicit operator CharT &() {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (none) {
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
throw value_error("Cannot convert None to a character");
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
|
|
|
|
auto &value = static_cast<StringType &>(str_caster);
|
|
|
|
size_t str_len = value.size();
|
2022-02-08 00:23:20 +00:00
|
|
|
if (str_len == 0) {
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
throw value_error("Cannot convert empty string to a character");
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
|
|
|
|
// If we're in UTF-8 mode, we have two possible failures: one for a unicode character that
|
2022-02-10 20:17:07 +00:00
|
|
|
// is too high, and one for multiple unicode characters (caught later), so we need to
|
|
|
|
// figure out how long the first encoded character is in bytes to distinguish between these
|
|
|
|
// two errors. We also allow want to allow unicode characters U+0080 through U+00FF, as
|
|
|
|
// those can fit into a single char value.
|
2022-11-28 15:39:38 +00:00
|
|
|
if (StringCaster::UTF_N == 8 && str_len > 1 && str_len <= 4) {
|
2020-09-11 03:20:47 +00:00
|
|
|
auto v0 = static_cast<unsigned char>(value[0]);
|
2021-07-27 22:32:26 +00:00
|
|
|
// low bits only: 0-127
|
|
|
|
// 0b110xxxxx - start of 2-byte sequence
|
|
|
|
// 0b1110xxxx - start of 3-byte sequence
|
|
|
|
// 0b11110xxx - start of 4-byte sequence
|
|
|
|
size_t char0_bytes = (v0 & 0x80) == 0 ? 1
|
|
|
|
: (v0 & 0xE0) == 0xC0 ? 2
|
|
|
|
: (v0 & 0xF0) == 0xE0 ? 3
|
|
|
|
: 4;
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
|
|
|
|
if (char0_bytes == str_len) {
|
|
|
|
// If we have a 128-255 value, we can decode it into a single char:
|
|
|
|
if (char0_bytes == 2 && (v0 & 0xFC) == 0xC0) { // 0x110000xx 0x10xxxxxx
|
2022-02-10 20:17:07 +00:00
|
|
|
one_char = static_cast<CharT>(((v0 & 3) << 6)
|
|
|
|
+ (static_cast<unsigned char>(value[1]) & 0x3F));
|
2017-10-06 14:50:10 +00:00
|
|
|
return one_char;
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
}
|
|
|
|
// Otherwise we have a single character, but it's > U+00FF
|
|
|
|
throw value_error("Character code point not in range(0x100)");
|
|
|
|
}
|
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
// UTF-16 is much easier: we can only have a surrogate pair for values above U+FFFF, thus a
|
|
|
|
// surrogate pair with total length 2 instantly indicates a range error (but not a "your
|
|
|
|
// string was too long" error).
|
2022-11-28 15:39:38 +00:00
|
|
|
else if (StringCaster::UTF_N == 16 && str_len == 2) {
|
2017-10-06 14:50:10 +00:00
|
|
|
one_char = static_cast<CharT>(value[0]);
|
2022-02-08 00:23:20 +00:00
|
|
|
if (one_char >= 0xD800 && one_char < 0xE000) {
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
throw value_error("Character code point not in range(0x10000)");
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
}
|
2016-03-26 22:37:51 +00:00
|
|
|
|
2022-02-08 00:23:20 +00:00
|
|
|
if (str_len != 1) {
|
Unicode fixes and docs (#624)
* Propagate unicode conversion failure
If returning a std::string with invalid utf-8 data, we currently fail
with an uninformative TypeError instead of propagating the
UnicodeDecodeError that Python sets on failure.
* Add support for u16/u32strings and literals
This adds support for wchar{16,32}_t character literals and the
associated std::u{16,32}string types. It also folds the
character/string conversion into a single type_caster template, since
the type casters for string and wstring were mostly the same anyway.
* Added too-long and too-big character conversion errors
With this commit, when casting to a single character, as opposed to a
C-style string, we make sure the input wasn't a multi-character string
or a single character with codepoint too large for the character type.
This also changes the character cast op to CharT instead of CharT& (we
need to be able to return a temporary decoded char value, but also
because there's little gained by bothering with an lvalue return here).
Finally it changes the char caster to 'has-a-string-caster' instead of
'is-a-string-caster' because, with the cast_op change above, there's
nothing at all gained from inheritance. This also lets us remove the
`success` from the string caster (which was only there for the char
caster) into the char caster itself. (I also renamed it to 'none' and
inverted its value to better reflect its purpose). The None -> nullptr
loading also now takes place only under a `convert = true` load pass.
Although it's unlikely that a function taking a char also has overloads
that can take a None, it seems marginally more correct to treat it as a
conversion.
This commit simplifies the size assumptions about character sizes with
static_asserts to back them up.
2017-02-14 10:08:19 +00:00
|
|
|
throw value_error("Expected a character, but multi-character string found");
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-03-02 07:07:08 +00:00
|
|
|
|
2017-10-06 14:50:10 +00:00
|
|
|
one_char = value[0];
|
|
|
|
return one_char;
|
2016-03-26 22:38:46 +00:00
|
|
|
}
|
2016-03-02 07:07:08 +00:00
|
|
|
|
2021-12-21 19:24:21 +00:00
|
|
|
static constexpr auto name = const_name(PYBIND11_STRING_NAME);
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename _T>
|
|
|
|
using cast_op_type = pybind11::detail::cast_op_type<_T>;
|
2016-03-02 07:07:08 +00:00
|
|
|
};
|
|
|
|
|
2017-07-04 18:57:41 +00:00
|
|
|
// Base implementation for std::tuple and std::pair
|
2022-02-10 20:17:07 +00:00
|
|
|
template <template <typename...> class Tuple, typename... Ts>
|
|
|
|
class tuple_caster {
|
2017-07-03 23:12:09 +00:00
|
|
|
using type = Tuple<Ts...>;
|
|
|
|
static constexpr auto size = sizeof...(Ts);
|
2017-07-04 18:57:41 +00:00
|
|
|
using indices = make_index_sequence<size>;
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
public:
|
2016-01-17 21:36:44 +00:00
|
|
|
bool load(handle src, bool convert) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!isinstance<sequence>(src)) {
|
2016-11-27 19:32:04 +00:00
|
|
|
return false;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-11-27 19:32:04 +00:00
|
|
|
const auto seq = reinterpret_borrow<sequence>(src);
|
2022-02-08 00:23:20 +00:00
|
|
|
if (seq.size() != size) {
|
2016-05-10 14:59:01 +00:00
|
|
|
return false;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-11-27 19:32:04 +00:00
|
|
|
return load_impl(seq, convert, indices{});
|
2016-05-10 14:59:01 +00:00
|
|
|
}
|
2016-05-26 12:29:31 +00:00
|
|
|
|
2017-07-03 23:12:09 +00:00
|
|
|
template <typename T>
|
|
|
|
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
|
|
|
return cast_impl(std::forward<T>(src), policy, parent, indices{});
|
2016-08-03 23:40:40 +00:00
|
|
|
}
|
2016-09-06 04:02:29 +00:00
|
|
|
|
2020-07-28 19:44:19 +00:00
|
|
|
// copied from the PYBIND11_TYPE_CASTER macro
|
|
|
|
template <typename T>
|
|
|
|
static handle cast(T *src, return_value_policy policy, handle parent) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!src) {
|
|
|
|
return none().release();
|
|
|
|
}
|
2020-07-28 19:44:19 +00:00
|
|
|
if (policy == return_value_policy::take_ownership) {
|
2021-07-09 13:45:53 +00:00
|
|
|
auto h = cast(std::move(*src), policy, parent);
|
|
|
|
delete src;
|
|
|
|
return h;
|
2020-07-28 19:44:19 +00:00
|
|
|
}
|
2021-07-09 13:45:53 +00:00
|
|
|
return cast(*src, policy, parent);
|
2020-07-28 19:44:19 +00:00
|
|
|
}
|
|
|
|
|
2024-03-27 20:51:03 +00:00
|
|
|
static constexpr auto name = const_name("tuple[")
|
|
|
|
+ ::pybind11::detail::concat(make_caster<Ts>::name...)
|
|
|
|
+ const_name("]");
|
2015-07-26 14:33:49 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
using cast_op_type = type;
|
2016-03-26 22:04:10 +00:00
|
|
|
|
CodeHealth: Enabling clang-tidy google-explicit-constructor (#3250)
* Adding google-explicit-constructor to .clang-tidy
* clang-tidy explicit attr.h (all automatic)
* clang-tidy explicit cast.h (all automatic)
* clang-tidy detail/init.h (1 NOLINT)
* clang-tidy detail/type_caster_base.h (2 NOLINT)
* clang-tidy pybind11.h (7 NOLINT)
* clang-tidy detail/common.h (3 NOLINT)
* clang-tidy detail/descr.h (2 NOLINT)
* clang-tidy pytypes.h (23 NOLINT, only 1 explicit)
* clang-tidy eigen.h (7 NOLINT, 0 explicit)
* Adding 2 explicit in functional.h
* Adding 4 explicit in iostream.h
* clang-tidy numpy.h (1 NOLINT, 1 explicit)
* clang-tidy embed.h (0 NOLINT, 1 explicit)
* clang-tidy tests/local_bindings.h (0 NOLINT, 4 explicit)
* clang-tidy tests/pybind11_cross_module_tests.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/pybind11_tests.h (0 NOLINT, 2 explicit)
* clang-tidy tests/test_buffers.cpp (0 NOLINT, 2 explicit)
* clang-tidy tests/test_builtin_casters.cpp (0 NOLINT, 4 explicit)
* clang-tidy tests/test_class.cpp (0 NOLINT, 6 explicit)
* clang-tidy tests/test_copy_move.cpp (0 NOLINT, 7 explicit)
* clang-tidy tests/test_embed/external_module.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/test_embed/test_interpreter.cpp (0 NOLINT, 1 explicit)
* clang-tidy tests/object.h (0 NOLINT, 2 explicit)
* clang-tidy batch of fully automatic fixes.
* Workaround for MSVC 19.16.27045.0 C++17 Python 2 C++ syntax error.
2021-09-09 01:53:38 +00:00
|
|
|
explicit operator type() & { return implicit_cast(indices{}); }
|
|
|
|
explicit operator type() && { return std::move(*this).implicit_cast(indices{}); }
|
2015-07-26 14:33:49 +00:00
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
protected:
|
2016-11-27 17:19:34 +00:00
|
|
|
template <size_t... Is>
|
2022-02-10 20:17:07 +00:00
|
|
|
type implicit_cast(index_sequence<Is...>) & {
|
|
|
|
return type(cast_op<Ts>(std::get<Is>(subcasters))...);
|
|
|
|
}
|
2017-05-14 19:57:26 +00:00
|
|
|
template <size_t... Is>
|
2022-02-10 20:17:07 +00:00
|
|
|
type implicit_cast(index_sequence<Is...>) && {
|
|
|
|
return type(cast_op<Ts>(std::move(std::get<Is>(subcasters)))...);
|
|
|
|
}
|
2017-05-14 19:57:26 +00:00
|
|
|
|
2016-11-27 19:32:04 +00:00
|
|
|
static constexpr bool load_impl(const sequence &, bool, index_sequence<>) { return true; }
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-11-27 17:19:34 +00:00
|
|
|
template <size_t... Is>
|
2016-11-27 19:32:04 +00:00
|
|
|
bool load_impl(const sequence &seq, bool convert, index_sequence<Is...>) {
|
2019-12-30 00:26:32 +00:00
|
|
|
#ifdef __cpp_fold_expressions
|
2022-02-08 00:23:20 +00:00
|
|
|
if ((... || !std::get<Is>(subcasters).load(seq[Is], convert))) {
|
2019-12-30 00:26:32 +00:00
|
|
|
return false;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2019-12-30 00:26:32 +00:00
|
|
|
#else
|
2022-02-10 17:23:15 +00:00
|
|
|
for (bool r : {std::get<Is>(subcasters).load(seq[Is], convert)...}) {
|
|
|
|
if (!r) {
|
2015-07-05 18:05:44 +00:00
|
|
|
return false;
|
2022-02-10 17:23:15 +00:00
|
|
|
}
|
|
|
|
}
|
2019-12-30 00:26:32 +00:00
|
|
|
#endif
|
2015-07-05 18:05:44 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Implementation: Convert a C++ tuple into a Python tuple */
|
2017-07-03 23:12:09 +00:00
|
|
|
template <typename T, size_t... Is>
|
2022-02-10 20:17:07 +00:00
|
|
|
static handle
|
|
|
|
cast_impl(T &&src, return_value_policy policy, handle parent, index_sequence<Is...>) {
|
2021-07-29 00:01:21 +00:00
|
|
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(src, policy, parent);
|
2021-08-06 19:27:11 +00:00
|
|
|
PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(policy, parent);
|
2022-02-10 20:17:07 +00:00
|
|
|
std::array<object, size> entries{{reinterpret_steal<object>(
|
|
|
|
make_caster<Ts>::cast(std::get<Is>(std::forward<T>(src)), policy, parent))...}};
|
2022-02-08 00:23:20 +00:00
|
|
|
for (const auto &entry : entries) {
|
|
|
|
if (!entry) {
|
2016-01-17 21:36:44 +00:00
|
|
|
return handle();
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
tuple result(size);
|
2015-12-30 20:03:57 +00:00
|
|
|
int counter = 0;
|
2022-02-08 00:23:20 +00:00
|
|
|
for (auto &entry : entries) {
|
2016-01-17 21:36:44 +00:00
|
|
|
PyTuple_SET_ITEM(result.ptr(), counter++, entry.release().ptr());
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
return result.release();
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2017-07-03 23:12:09 +00:00
|
|
|
Tuple<make_caster<Ts>...> subcasters;
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T1, typename T2>
|
|
|
|
class type_caster<std::pair<T1, T2>> : public tuple_caster<std::pair, T1, T2> {};
|
2017-07-04 18:57:41 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename... Ts>
|
|
|
|
class type_caster<std::tuple<Ts...>> : public tuple_caster<std::tuple, Ts...> {};
|
2017-07-04 18:57:41 +00:00
|
|
|
|
2024-06-30 16:52:37 +00:00
|
|
|
template <>
|
|
|
|
class type_caster<std::tuple<>> : public tuple_caster<std::tuple> {
|
|
|
|
public:
|
|
|
|
// PEP 484 specifies this syntax for an empty tuple
|
|
|
|
static constexpr auto name = const_name("tuple[()]");
|
|
|
|
};
|
|
|
|
|
2017-01-31 16:05:44 +00:00
|
|
|
/// Helper class which abstracts away certain actions. Users can provide specializations for
|
|
|
|
/// custom holders, but it's only necessary if the type has a non-standard interface.
|
|
|
|
template <typename T>
|
|
|
|
struct holder_helper {
|
|
|
|
static auto get(const T &p) -> decltype(p.get()) { return p.get(); }
|
|
|
|
};
|
|
|
|
|
2024-07-31 13:17:31 +00:00
|
|
|
// SMART_HOLDER_BAKEIN_FOLLOW_ON: Rewrite comment, with reference to shared_ptr specialization.
|
2015-07-05 18:05:44 +00:00
|
|
|
/// Type caster for holder types like std::shared_ptr, etc.
|
2021-01-30 20:02:24 +00:00
|
|
|
/// The SFINAE hook is provided to help work around the current lack of support
|
|
|
|
/// for smart-pointer interoperability. Please consider it an implementation
|
|
|
|
/// detail that may change in the future, as formal support for smart-pointer
|
|
|
|
/// interoperability is added into pybind11.
|
|
|
|
template <typename type, typename holder_type, typename SFINAE = void>
|
2017-01-31 16:05:44 +00:00
|
|
|
struct copyable_holder_caster : public type_caster_base<type> {
|
2015-07-05 18:05:44 +00:00
|
|
|
public:
|
2016-09-11 11:00:40 +00:00
|
|
|
using base = type_caster_base<type>;
|
2017-04-07 15:11:14 +00:00
|
|
|
static_assert(std::is_base_of<base, type_caster<type>>::value,
|
2022-02-10 20:17:07 +00:00
|
|
|
"Holder classes are only supported for custom types");
|
2016-09-11 11:00:40 +00:00
|
|
|
using base::base;
|
|
|
|
using base::cast;
|
|
|
|
using base::typeinfo;
|
|
|
|
using base::value;
|
2015-11-24 22:05:58 +00:00
|
|
|
|
2017-02-23 02:36:09 +00:00
|
|
|
bool load(handle src, bool convert) {
|
|
|
|
return base::template load_impl<copyable_holder_caster<type, holder_type>>(src, convert);
|
2016-09-11 11:00:40 +00:00
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
explicit operator type *() { return this->value; }
|
2020-06-03 10:12:51 +00:00
|
|
|
// static_cast works around compiler error with MSVC 17 and CUDA 10.2
|
|
|
|
// see issue #2180
|
2022-02-10 20:17:07 +00:00
|
|
|
explicit operator type &() { return *(static_cast<type *>(this->value)); }
|
|
|
|
explicit operator holder_type *() { return std::addressof(holder); }
|
|
|
|
explicit operator holder_type &() { return holder; }
|
2016-01-17 21:36:44 +00:00
|
|
|
|
2017-02-23 02:36:09 +00:00
|
|
|
static handle cast(const holder_type &src, return_value_policy, handle) {
|
|
|
|
const auto *ptr = holder_helper<holder_type>::get(src);
|
|
|
|
return type_caster_base<type>::cast_holder(ptr, &src);
|
|
|
|
}
|
2016-09-11 11:00:40 +00:00
|
|
|
|
2017-02-23 02:36:09 +00:00
|
|
|
protected:
|
|
|
|
friend class type_caster_generic;
|
|
|
|
void check_holder_compat() {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (typeinfo->default_holder) {
|
2017-02-23 02:36:09 +00:00
|
|
|
throw cast_error("Unable to load a custom holder type from a default-holder instance");
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-09-11 11:00:40 +00:00
|
|
|
}
|
|
|
|
|
2024-07-19 00:34:06 +00:00
|
|
|
void load_value(value_and_holder &&v_h) {
|
2017-02-23 02:36:09 +00:00
|
|
|
if (v_h.holder_constructed()) {
|
|
|
|
value = v_h.value_ptr();
|
2017-10-22 15:06:52 +00:00
|
|
|
holder = v_h.template holder<holder_type>();
|
2024-07-19 00:34:06 +00:00
|
|
|
return;
|
2021-07-09 13:45:53 +00:00
|
|
|
}
|
|
|
|
throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) "
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
|
|
|
"(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for "
|
|
|
|
"type information)");
|
2016-12-07 01:36:44 +00:00
|
|
|
#else
|
2021-07-09 13:45:53 +00:00
|
|
|
"of type '"
|
|
|
|
+ type_id<holder_type>() + "''");
|
2016-12-07 01:36:44 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T = holder_type,
|
|
|
|
detail::enable_if_t<!std::is_constructible<T, const T &, type *>::value, int> = 0>
|
|
|
|
bool try_implicit_casts(handle, bool) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-09-11 11:00:40 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T = holder_type,
|
|
|
|
detail::enable_if_t<std::is_constructible<T, const T &, type *>::value, int> = 0>
|
2016-09-11 11:00:40 +00:00
|
|
|
bool try_implicit_casts(handle src, bool convert) {
|
|
|
|
for (auto &cast : typeinfo->implicit_casts) {
|
2017-01-31 16:05:44 +00:00
|
|
|
copyable_holder_caster sub_caster(*cast.first);
|
2016-09-11 11:00:40 +00:00
|
|
|
if (sub_caster.load(src, convert)) {
|
|
|
|
value = cast.second(sub_caster.value);
|
|
|
|
holder = holder_type(sub_caster.holder, (type *) value);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2016-01-17 21:36:40 +00:00
|
|
|
return false;
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
2015-11-24 22:05:58 +00:00
|
|
|
|
2017-07-03 23:27:18 +00:00
|
|
|
static bool try_direct_conversions(handle) { return false; }
|
2016-02-18 17:38:27 +00:00
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
holder_type holder;
|
|
|
|
};
|
|
|
|
|
2024-07-31 13:17:31 +00:00
|
|
|
#ifdef PYBIND11_HAVE_INTERNALS_WITH_SMART_HOLDER_SUPPORT
|
|
|
|
|
|
|
|
template <typename, typename SFINAE = void>
|
|
|
|
struct copyable_holder_caster_shared_ptr_with_smart_holder_support_enabled : std::true_type {};
|
|
|
|
|
|
|
|
// SMART_HOLDER_BAKEIN_FOLLOW_ON: Refactor copyable_holder_caster to reduce code duplication.
|
|
|
|
template <typename type>
|
|
|
|
struct copyable_holder_caster<
|
|
|
|
type,
|
|
|
|
std::shared_ptr<type>,
|
|
|
|
enable_if_t<copyable_holder_caster_shared_ptr_with_smart_holder_support_enabled<type>::value>>
|
|
|
|
: public type_caster_base<type> {
|
|
|
|
public:
|
|
|
|
using base = type_caster_base<type>;
|
|
|
|
static_assert(std::is_base_of<base, type_caster<type>>::value,
|
|
|
|
"Holder classes are only supported for custom types");
|
|
|
|
using base::base;
|
|
|
|
using base::cast;
|
|
|
|
using base::typeinfo;
|
|
|
|
using base::value;
|
|
|
|
|
|
|
|
bool load(handle src, bool convert) {
|
|
|
|
return base::template load_impl<copyable_holder_caster<type, std::shared_ptr<type>>>(
|
|
|
|
src, convert);
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit operator std::shared_ptr<type> *() {
|
|
|
|
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
|
|
|
|
pybind11_fail("Passing `std::shared_ptr<T> *` from Python to C++ is not supported "
|
|
|
|
"(inherently unsafe).");
|
|
|
|
}
|
|
|
|
return std::addressof(shared_ptr_holder);
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit operator std::shared_ptr<type> &() {
|
|
|
|
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
|
|
|
|
shared_ptr_holder = sh_load_helper.load_as_shared_ptr(value);
|
|
|
|
}
|
|
|
|
return shared_ptr_holder;
|
|
|
|
}
|
|
|
|
|
|
|
|
static handle
|
|
|
|
cast(const std::shared_ptr<type> &src, return_value_policy policy, handle parent) {
|
|
|
|
const auto *ptr = src.get();
|
|
|
|
auto st = type_caster_base<type>::src_and_type(ptr);
|
|
|
|
if (st.second == nullptr) {
|
|
|
|
return handle(); // no type info: error will be set already
|
|
|
|
}
|
|
|
|
if (st.second->holder_enum_v == detail::holder_enum_t::smart_holder) {
|
|
|
|
return smart_holder_type_caster_support::smart_holder_from_shared_ptr(
|
|
|
|
src, policy, parent, st);
|
|
|
|
}
|
|
|
|
return type_caster_base<type>::cast_holder(ptr, &src);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This function will succeed even if the `responsible_parent` does not own the
|
|
|
|
// wrapped C++ object directly.
|
|
|
|
// It is the responsibility of the caller to ensure that the `responsible_parent`
|
|
|
|
// has a `keep_alive` relationship with the owner of the wrapped C++ object, or
|
|
|
|
// that the wrapped C++ object lives for the duration of the process.
|
|
|
|
static std::shared_ptr<type> shared_ptr_with_responsible_parent(handle responsible_parent) {
|
|
|
|
copyable_holder_caster loader;
|
|
|
|
loader.load(responsible_parent, /*convert=*/false);
|
|
|
|
assert(loader.typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder);
|
|
|
|
return loader.sh_load_helper.load_as_shared_ptr(loader.value, responsible_parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
friend class type_caster_generic;
|
|
|
|
void check_holder_compat() {
|
|
|
|
if (typeinfo->default_holder) {
|
|
|
|
throw cast_error("Unable to load a custom holder type from a default-holder instance");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void load_value(value_and_holder &&v_h) {
|
|
|
|
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
|
|
|
|
sh_load_helper.loaded_v_h = v_h;
|
|
|
|
value = sh_load_helper.get_void_ptr_or_nullptr();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (v_h.holder_constructed()) {
|
|
|
|
value = v_h.value_ptr();
|
|
|
|
shared_ptr_holder = v_h.template holder<std::shared_ptr<type>>();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) "
|
|
|
|
# if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
|
|
|
"(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for "
|
|
|
|
"type information)");
|
|
|
|
# else
|
|
|
|
"of type '"
|
|
|
|
+ type_id<std::shared_ptr<type>>() + "''");
|
|
|
|
# endif
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T = std::shared_ptr<type>,
|
|
|
|
detail::enable_if_t<!std::is_constructible<T, const T &, type *>::value, int> = 0>
|
|
|
|
bool try_implicit_casts(handle, bool) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T = std::shared_ptr<type>,
|
|
|
|
detail::enable_if_t<std::is_constructible<T, const T &, type *>::value, int> = 0>
|
|
|
|
bool try_implicit_casts(handle src, bool convert) {
|
|
|
|
for (auto &cast : typeinfo->implicit_casts) {
|
|
|
|
copyable_holder_caster sub_caster(*cast.first);
|
|
|
|
if (sub_caster.load(src, convert)) {
|
|
|
|
value = cast.second(sub_caster.value);
|
|
|
|
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
|
|
|
|
sh_load_helper.loaded_v_h = sub_caster.sh_load_helper.loaded_v_h;
|
|
|
|
} else {
|
|
|
|
shared_ptr_holder
|
|
|
|
= std::shared_ptr<type>(sub_caster.shared_ptr_holder, (type *) value);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool try_direct_conversions(handle) { return false; }
|
|
|
|
|
|
|
|
std::shared_ptr<type> shared_ptr_holder;
|
|
|
|
smart_holder_type_caster_support::load_helper<remove_cv_t<type>> sh_load_helper; // Const2Mutbl
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // PYBIND11_HAVE_INTERNALS_WITH_SMART_HOLDER_SUPPORT
|
|
|
|
|
2016-10-18 11:56:33 +00:00
|
|
|
/// Specialize for the common std::shared_ptr, so users don't need to
|
|
|
|
template <typename T>
|
2022-02-10 20:17:07 +00:00
|
|
|
class type_caster<std::shared_ptr<T>> : public copyable_holder_caster<T, std::shared_ptr<T>> {};
|
2017-01-31 16:05:44 +00:00
|
|
|
|
2024-07-31 13:17:31 +00:00
|
|
|
// SMART_HOLDER_BAKEIN_FOLLOW_ON: Rewrite comment, with reference to unique_ptr specialization.
|
2021-01-30 20:02:24 +00:00
|
|
|
/// Type caster for holder types like std::unique_ptr.
|
|
|
|
/// Please consider the SFINAE hook an implementation detail, as explained
|
|
|
|
/// in the comment for the copyable_holder_caster.
|
|
|
|
template <typename type, typename holder_type, typename SFINAE = void>
|
2017-01-31 16:05:44 +00:00
|
|
|
struct move_only_holder_caster {
|
2017-04-07 15:11:14 +00:00
|
|
|
static_assert(std::is_base_of<type_caster_base<type>, type_caster<type>>::value,
|
2022-02-10 20:17:07 +00:00
|
|
|
"Holder classes are only supported for custom types");
|
2017-04-07 15:11:14 +00:00
|
|
|
|
2017-01-31 16:05:44 +00:00
|
|
|
static handle cast(holder_type &&src, return_value_policy, handle) {
|
|
|
|
auto *ptr = holder_helper<holder_type>::get(src);
|
2018-06-20 15:33:50 +00:00
|
|
|
return type_caster_base<type>::cast_holder(ptr, std::addressof(src));
|
2017-01-31 16:05:44 +00:00
|
|
|
}
|
2017-07-02 09:48:56 +00:00
|
|
|
static constexpr auto name = type_caster_base<type>::name;
|
2017-01-31 16:05:44 +00:00
|
|
|
};
|
|
|
|
|
2024-07-31 13:17:31 +00:00
|
|
|
#ifdef PYBIND11_HAVE_INTERNALS_WITH_SMART_HOLDER_SUPPORT
|
|
|
|
|
|
|
|
template <typename, typename SFINAE = void>
|
|
|
|
struct move_only_holder_caster_unique_ptr_with_smart_holder_support_enabled : std::true_type {};
|
|
|
|
|
|
|
|
// SMART_HOLDER_BAKEIN_FOLLOW_ON: Refactor move_only_holder_caster to reduce code duplication.
|
|
|
|
template <typename type, typename deleter>
|
|
|
|
struct move_only_holder_caster<
|
|
|
|
type,
|
|
|
|
std::unique_ptr<type, deleter>,
|
|
|
|
enable_if_t<move_only_holder_caster_unique_ptr_with_smart_holder_support_enabled<type>::value>>
|
|
|
|
: public type_caster_base<type> {
|
|
|
|
public:
|
|
|
|
using base = type_caster_base<type>;
|
|
|
|
static_assert(std::is_base_of<base, type_caster<type>>::value,
|
|
|
|
"Holder classes are only supported for custom types");
|
|
|
|
using base::base;
|
|
|
|
using base::cast;
|
|
|
|
using base::typeinfo;
|
|
|
|
using base::value;
|
|
|
|
|
|
|
|
static handle
|
|
|
|
cast(std::unique_ptr<type, deleter> &&src, return_value_policy policy, handle parent) {
|
|
|
|
auto *ptr = src.get();
|
|
|
|
auto st = type_caster_base<type>::src_and_type(ptr);
|
|
|
|
if (st.second == nullptr) {
|
|
|
|
return handle(); // no type info: error will be set already
|
|
|
|
}
|
|
|
|
if (st.second->holder_enum_v == detail::holder_enum_t::smart_holder) {
|
|
|
|
return smart_holder_type_caster_support::smart_holder_from_unique_ptr(
|
|
|
|
std::move(src), policy, parent, st);
|
|
|
|
}
|
|
|
|
return type_caster_generic::cast(st.first,
|
|
|
|
return_value_policy::take_ownership,
|
|
|
|
{},
|
|
|
|
st.second,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
std::addressof(src));
|
|
|
|
}
|
|
|
|
|
|
|
|
static handle
|
|
|
|
cast(const std::unique_ptr<type, deleter> &src, return_value_policy policy, handle parent) {
|
|
|
|
if (!src) {
|
|
|
|
return none().release();
|
|
|
|
}
|
|
|
|
if (policy == return_value_policy::automatic) {
|
|
|
|
policy = return_value_policy::reference_internal;
|
|
|
|
}
|
|
|
|
if (policy != return_value_policy::reference_internal) {
|
|
|
|
throw cast_error("Invalid return_value_policy for unique_ptr&");
|
|
|
|
}
|
|
|
|
return type_caster_base<type>::cast(src.get(), policy, parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool load(handle src, bool convert) {
|
|
|
|
return base::template load_impl<
|
|
|
|
move_only_holder_caster<type, std::unique_ptr<type, deleter>>>(src, convert);
|
|
|
|
}
|
|
|
|
|
|
|
|
void load_value(value_and_holder &&v_h) {
|
|
|
|
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
|
|
|
|
sh_load_helper.loaded_v_h = v_h;
|
|
|
|
sh_load_helper.loaded_v_h.type = typeinfo;
|
|
|
|
value = sh_load_helper.get_void_ptr_or_nullptr();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pybind11_fail(
|
|
|
|
"Passing `std::unique_ptr<T>` from Python to C++ requires `py::classh` (with T = "
|
|
|
|
+ clean_type_id(typeinfo->cpptype->name()) + ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename>
|
|
|
|
using cast_op_type = std::unique_ptr<type, deleter>;
|
|
|
|
|
|
|
|
explicit operator std::unique_ptr<type, deleter>() {
|
|
|
|
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
|
|
|
|
return sh_load_helper.template load_as_unique_ptr<deleter>(value);
|
|
|
|
}
|
|
|
|
pybind11_fail("Expected to be UNREACHABLE: " __FILE__ ":" PYBIND11_TOSTRING(__LINE__));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool try_implicit_casts(handle src, bool convert) {
|
|
|
|
for (auto &cast : typeinfo->implicit_casts) {
|
|
|
|
move_only_holder_caster sub_caster(*cast.first);
|
|
|
|
if (sub_caster.load(src, convert)) {
|
|
|
|
value = cast.second(sub_caster.value);
|
|
|
|
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
|
|
|
|
sh_load_helper.loaded_v_h = sub_caster.sh_load_helper.loaded_v_h;
|
|
|
|
} else {
|
|
|
|
pybind11_fail("Expected to be UNREACHABLE: " __FILE__
|
|
|
|
":" PYBIND11_TOSTRING(__LINE__));
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool try_direct_conversions(handle) { return false; }
|
|
|
|
|
|
|
|
smart_holder_type_caster_support::load_helper<remove_cv_t<type>> sh_load_helper; // Const2Mutbl
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // PYBIND11_HAVE_INTERNALS_WITH_SMART_HOLDER_SUPPORT
|
|
|
|
|
2017-01-31 16:05:44 +00:00
|
|
|
template <typename type, typename deleter>
|
|
|
|
class type_caster<std::unique_ptr<type, deleter>>
|
2022-02-10 20:17:07 +00:00
|
|
|
: public move_only_holder_caster<type, std::unique_ptr<type, deleter>> {};
|
2017-01-31 16:05:44 +00:00
|
|
|
|
|
|
|
template <typename type, typename holder_type>
|
2017-07-27 18:55:17 +00:00
|
|
|
using type_caster_holder = conditional_t<is_copy_constructible<holder_type>::value,
|
2017-01-31 16:05:44 +00:00
|
|
|
copyable_holder_caster<type, holder_type>,
|
|
|
|
move_only_holder_caster<type, holder_type>>;
|
2016-10-18 11:56:33 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T, bool Value = false>
|
|
|
|
struct always_construct_holder {
|
|
|
|
static constexpr bool value = Value;
|
|
|
|
};
|
2016-12-15 22:44:23 +00:00
|
|
|
|
2016-10-18 11:56:33 +00:00
|
|
|
/// Create a specialization for custom holder types (silently ignores std::shared_ptr)
|
2022-02-10 20:17:07 +00:00
|
|
|
#define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type, ...) \
|
2022-07-06 21:29:20 +00:00
|
|
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) \
|
2022-02-10 20:17:07 +00:00
|
|
|
namespace detail { \
|
|
|
|
template <typename type> \
|
|
|
|
struct always_construct_holder<holder_type> : always_construct_holder<void, ##__VA_ARGS__> { \
|
|
|
|
}; \
|
|
|
|
template <typename type> \
|
|
|
|
class type_caster<holder_type, enable_if_t<!is_shared_ptr<holder_type>::value>> \
|
|
|
|
: public type_caster_holder<type, holder_type> {}; \
|
|
|
|
} \
|
2022-07-06 21:29:20 +00:00
|
|
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
2016-10-18 11:56:33 +00:00
|
|
|
|
2016-09-06 16:27:00 +00:00
|
|
|
// PYBIND11_DECLARE_HOLDER_TYPE holder types:
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename base, typename holder>
|
|
|
|
struct is_holder_type
|
|
|
|
: std::is_base_of<detail::type_caster_holder<base, holder>, detail::type_caster<holder>> {};
|
2024-07-31 13:17:31 +00:00
|
|
|
|
|
|
|
// Specializations for always-supported holders:
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename base, typename deleter>
|
|
|
|
struct is_holder_type<base, std::unique_ptr<base, deleter>> : std::true_type {};
|
|
|
|
|
2024-07-31 13:17:31 +00:00
|
|
|
#ifdef PYBIND11_HAVE_INTERNALS_WITH_SMART_HOLDER_SUPPORT
|
|
|
|
template <typename base>
|
|
|
|
struct is_holder_type<base, smart_holder> : std::true_type {};
|
|
|
|
#endif
|
|
|
|
|
2024-03-27 19:39:05 +00:00
|
|
|
#ifdef PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION // See PR #4888
|
|
|
|
|
|
|
|
// This leads to compilation errors if a specialization is missing.
|
|
|
|
template <typename T>
|
|
|
|
struct handle_type_name;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
struct handle_type_name {
|
|
|
|
static constexpr auto name = const_name<T>();
|
|
|
|
};
|
2024-03-27 19:39:05 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<object> {
|
|
|
|
static constexpr auto name = const_name("object");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<list> {
|
|
|
|
static constexpr auto name = const_name("list");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<dict> {
|
|
|
|
static constexpr auto name = const_name("dict");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<anyset> {
|
|
|
|
static constexpr auto name = const_name("Union[set, frozenset]");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<set> {
|
|
|
|
static constexpr auto name = const_name("set");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<frozenset> {
|
|
|
|
static constexpr auto name = const_name("frozenset");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<str> {
|
|
|
|
static constexpr auto name = const_name("str");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<tuple> {
|
|
|
|
static constexpr auto name = const_name("tuple");
|
|
|
|
};
|
2022-02-10 20:17:07 +00:00
|
|
|
template <>
|
|
|
|
struct handle_type_name<bool_> {
|
|
|
|
static constexpr auto name = const_name("bool");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<bytes> {
|
|
|
|
static constexpr auto name = const_name(PYBIND11_BYTES_NAME);
|
|
|
|
};
|
|
|
|
template <>
|
2023-09-12 19:47:39 +00:00
|
|
|
struct handle_type_name<buffer> {
|
|
|
|
static constexpr auto name = const_name("Buffer");
|
|
|
|
};
|
|
|
|
template <>
|
2022-02-10 20:17:07 +00:00
|
|
|
struct handle_type_name<int_> {
|
|
|
|
static constexpr auto name = const_name("int");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<iterable> {
|
|
|
|
static constexpr auto name = const_name("Iterable");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<iterator> {
|
|
|
|
static constexpr auto name = const_name("Iterator");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<float_> {
|
|
|
|
static constexpr auto name = const_name("float");
|
|
|
|
};
|
|
|
|
template <>
|
2023-08-31 05:43:01 +00:00
|
|
|
struct handle_type_name<function> {
|
|
|
|
static constexpr auto name = const_name("Callable");
|
|
|
|
};
|
|
|
|
template <>
|
2023-09-12 19:47:39 +00:00
|
|
|
struct handle_type_name<handle> {
|
|
|
|
static constexpr auto name = handle_type_name<object>::name;
|
|
|
|
};
|
|
|
|
template <>
|
2022-02-10 20:17:07 +00:00
|
|
|
struct handle_type_name<none> {
|
|
|
|
static constexpr auto name = const_name("None");
|
|
|
|
};
|
|
|
|
template <>
|
2023-09-12 19:47:39 +00:00
|
|
|
struct handle_type_name<sequence> {
|
|
|
|
static constexpr auto name = const_name("Sequence");
|
|
|
|
};
|
|
|
|
template <>
|
2024-03-27 19:39:05 +00:00
|
|
|
struct handle_type_name<bytearray> {
|
|
|
|
static constexpr auto name = const_name("bytearray");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<memoryview> {
|
|
|
|
static constexpr auto name = const_name("memoryview");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<slice> {
|
|
|
|
static constexpr auto name = const_name("slice");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<type> {
|
|
|
|
static constexpr auto name = const_name("type");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<capsule> {
|
|
|
|
static constexpr auto name = const_name("capsule");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<ellipsis> {
|
|
|
|
static constexpr auto name = const_name("ellipsis");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<weakref> {
|
|
|
|
static constexpr auto name = const_name("weakref");
|
|
|
|
};
|
|
|
|
template <>
|
2022-02-10 20:17:07 +00:00
|
|
|
struct handle_type_name<args> {
|
|
|
|
static constexpr auto name = const_name("*args");
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<kwargs> {
|
|
|
|
static constexpr auto name = const_name("**kwargs");
|
|
|
|
};
|
2024-03-27 19:39:05 +00:00
|
|
|
template <>
|
|
|
|
struct handle_type_name<obj_attr_accessor> {
|
|
|
|
static constexpr auto name = const_name<obj_attr_accessor>();
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<str_attr_accessor> {
|
|
|
|
static constexpr auto name = const_name<str_attr_accessor>();
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<item_accessor> {
|
|
|
|
static constexpr auto name = const_name<item_accessor>();
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<sequence_accessor> {
|
|
|
|
static constexpr auto name = const_name<sequence_accessor>();
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<list_accessor> {
|
|
|
|
static constexpr auto name = const_name<list_accessor>();
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct handle_type_name<tuple_accessor> {
|
|
|
|
static constexpr auto name = const_name<tuple_accessor>();
|
|
|
|
};
|
2016-01-17 21:36:38 +00:00
|
|
|
|
2015-12-16 11:11:01 +00:00
|
|
|
template <typename type>
|
2016-10-23 12:50:08 +00:00
|
|
|
struct pyobject_caster {
|
Add anyset & frozenset, enable copying (cast) to std::set (#3901)
* Add frozenset, and allow it cast to std::set
For the reverse direction, std::set still casts to set. This is in concordance with the behavior for sequence containers, where e.g. tuple casts to std::vector but std::vector casts to list.
Extracted from #3886.
* Rename set_base to any_set to match Python C API
since this will be part of pybind11 public API
* PR: static_cast, anyset
* Add tests for frozenset
and rename anyset methods
* Remove frozenset default ctor, add tests
Making frozenset non-default constructible means that we need to adjust pyobject_caster to not require that its value is default constructible, by initializing value to a nil handle. This also allows writing C++ functions taking anyset, and is arguably a performance improvement, since there is no need to allocate an object that will just be replaced by load.
Add some more tests, including anyset::empty, anyset::size, set::add and set::clear.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Add rationale to `pyobject_caster` default ctor
* Remove ineffectual protected: access control
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-05-05 19:09:56 +00:00
|
|
|
template <typename T = type, enable_if_t<std::is_same<T, handle>::value, int> = 0>
|
|
|
|
pyobject_caster() : value() {}
|
|
|
|
|
|
|
|
// `type` may not be default constructible (e.g. frozenset, anyset). Initializing `value`
|
|
|
|
// to a nil handle is safe since it will only be accessed if `load` succeeds.
|
|
|
|
template <typename T = type, enable_if_t<std::is_base_of<object, T>::value, int> = 0>
|
|
|
|
pyobject_caster() : value(reinterpret_steal<type>(handle())) {}
|
|
|
|
|
2016-10-23 12:50:08 +00:00
|
|
|
template <typename T = type, enable_if_t<std::is_same<T, handle>::value, int> = 0>
|
2022-02-10 20:17:07 +00:00
|
|
|
bool load(handle src, bool /* convert */) {
|
|
|
|
value = src;
|
|
|
|
return static_cast<bool>(value);
|
|
|
|
}
|
2015-12-16 11:11:01 +00:00
|
|
|
|
2016-09-12 15:36:43 +00:00
|
|
|
template <typename T = type, enable_if_t<std::is_base_of<object, T>::value, int> = 0>
|
2016-10-23 12:50:08 +00:00
|
|
|
bool load(handle src, bool /* convert */) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!isinstance<type>(src)) {
|
2016-10-23 12:50:08 +00:00
|
|
|
return false;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-10-28 01:08:15 +00:00
|
|
|
value = reinterpret_borrow<type>(src);
|
2016-10-23 12:50:08 +00:00
|
|
|
return true;
|
|
|
|
}
|
2015-12-16 11:11:01 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) {
|
|
|
|
return src.inc_ref();
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
2017-07-02 09:48:56 +00:00
|
|
|
PYBIND11_TYPE_CASTER(type, handle_type_name<type>::name);
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
2016-10-23 12:50:08 +00:00
|
|
|
template <typename T>
|
2022-02-10 20:17:07 +00:00
|
|
|
class type_caster<T, enable_if_t<is_pyobject<T>::value>> : public pyobject_caster<T> {};
|
2016-10-23 12:50:08 +00:00
|
|
|
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
// Our conditions for enabling moving are quite restrictive:
|
|
|
|
// At compile time:
|
|
|
|
// - T needs to be a non-const, non-pointer, non-reference type
|
|
|
|
// - type_caster<T>::operator T&() must exist
|
|
|
|
// - the type must be move constructible (obviously)
|
|
|
|
// At run-time:
|
|
|
|
// - if the type is non-copy-constructible, the object must be the sole owner of the type (i.e. it
|
|
|
|
// must have ref_count() == 1)h
|
|
|
|
// If any of the above are not satisfied, we fall back to copying.
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
using move_is_plain_type
|
|
|
|
= satisfies_none_of<T, std::is_void, std::is_pointer, std::is_reference, std::is_const>;
|
|
|
|
template <typename T, typename SFINAE = void>
|
|
|
|
struct move_always : std::false_type {};
|
|
|
|
template <typename T>
|
|
|
|
struct move_always<
|
|
|
|
T,
|
|
|
|
enable_if_t<
|
|
|
|
all_of<move_is_plain_type<T>,
|
|
|
|
negation<is_copy_constructible<T>>,
|
2023-04-21 18:30:35 +00:00
|
|
|
is_move_constructible<T>,
|
2022-02-10 20:17:07 +00:00
|
|
|
std::is_same<decltype(std::declval<make_caster<T>>().operator T &()), T &>>::value>>
|
|
|
|
: std::true_type {};
|
|
|
|
template <typename T, typename SFINAE = void>
|
|
|
|
struct move_if_unreferenced : std::false_type {};
|
|
|
|
template <typename T>
|
|
|
|
struct move_if_unreferenced<
|
|
|
|
T,
|
|
|
|
enable_if_t<
|
|
|
|
all_of<move_is_plain_type<T>,
|
|
|
|
negation<move_always<T>>,
|
2023-04-21 18:30:35 +00:00
|
|
|
is_move_constructible<T>,
|
2022-02-10 20:17:07 +00:00
|
|
|
std::is_same<decltype(std::declval<make_caster<T>>().operator T &()), T &>>::value>>
|
|
|
|
: std::true_type {};
|
|
|
|
template <typename T>
|
|
|
|
using move_never = none_of<move_always<T>, move_if_unreferenced<T>>;
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
|
2016-09-07 17:38:32 +00:00
|
|
|
// Detect whether returning a `type` from a cast on type's type_caster is going to result in a
|
|
|
|
// reference or pointer to a local variable of the type_caster. Basically, only
|
|
|
|
// non-reference/pointer `type`s and reference/pointers from a type_caster_generic are safe;
|
|
|
|
// everything else returns a reference/pointer to a local variable.
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename type>
|
|
|
|
using cast_is_temporary_value_reference
|
|
|
|
= bool_constant<(std::is_reference<type>::value || std::is_pointer<type>::value)
|
|
|
|
&& !std::is_base_of<type_caster_generic, make_caster<type>>::value
|
|
|
|
&& !std::is_same<intrinsic_t<type>, void>::value>;
|
2016-09-07 17:38:32 +00:00
|
|
|
|
Add an ability to avoid forcing rvp::move
Eigen::Ref objects, when returned, are almost always returned as
rvalues; what's important is the data they reference, not the outer
shell, and so we want to be able to use `::copy`,
`::reference_internal`, etc. to refer to the data the Eigen::Ref
references (in the following commits), rather than the Eigen::Ref
instance itself.
This moves the policy override into a struct so that code that wants to
avoid it (or wants to provide some other Return-type-conditional
override) can create a specialization of
return_value_policy_override<Return> in order to override the override.
This lets an Eigen::Ref-returning function be bound with `rvp::copy`,
for example, to specify that the data should be copied into a new numpy
array rather than referenced, or `rvp::reference_internal` to indicate
that it should be referenced, but a keep-alive used (actually, we used
the array's `base` rather than a py::keep_alive in such a case, but it
accomplishes the same thing).
2017-01-20 05:59:26 +00:00
|
|
|
// When a value returned from a C++ function is being cast back to Python, we almost always want to
|
|
|
|
// force `policy = move`, regardless of the return value policy the function/method was declared
|
2018-07-17 14:56:26 +00:00
|
|
|
// with.
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename Return, typename SFINAE = void>
|
|
|
|
struct return_value_policy_override {
|
2018-07-17 14:56:26 +00:00
|
|
|
static return_value_policy policy(return_value_policy p) { return p; }
|
|
|
|
};
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename Return>
|
|
|
|
struct return_value_policy_override<
|
|
|
|
Return,
|
2024-07-31 13:17:31 +00:00
|
|
|
detail::enable_if_t<std::is_base_of<type_caster_generic, make_caster<Return>>::value, void>> {
|
Add an ability to avoid forcing rvp::move
Eigen::Ref objects, when returned, are almost always returned as
rvalues; what's important is the data they reference, not the outer
shell, and so we want to be able to use `::copy`,
`::reference_internal`, etc. to refer to the data the Eigen::Ref
references (in the following commits), rather than the Eigen::Ref
instance itself.
This moves the policy override into a struct so that code that wants to
avoid it (or wants to provide some other Return-type-conditional
override) can create a specialization of
return_value_policy_override<Return> in order to override the override.
This lets an Eigen::Ref-returning function be bound with `rvp::copy`,
for example, to specify that the data should be copied into a new numpy
array rather than referenced, or `rvp::reference_internal` to indicate
that it should be referenced, but a keep-alive used (actually, we used
the array's `base` rather than a py::keep_alive in such a case, but it
accomplishes the same thing).
2017-01-20 05:59:26 +00:00
|
|
|
static return_value_policy policy(return_value_policy p) {
|
2022-02-10 20:17:07 +00:00
|
|
|
return !std::is_lvalue_reference<Return>::value && !std::is_pointer<Return>::value
|
|
|
|
? return_value_policy::move
|
|
|
|
: p;
|
Add an ability to avoid forcing rvp::move
Eigen::Ref objects, when returned, are almost always returned as
rvalues; what's important is the data they reference, not the outer
shell, and so we want to be able to use `::copy`,
`::reference_internal`, etc. to refer to the data the Eigen::Ref
references (in the following commits), rather than the Eigen::Ref
instance itself.
This moves the policy override into a struct so that code that wants to
avoid it (or wants to provide some other Return-type-conditional
override) can create a specialization of
return_value_policy_override<Return> in order to override the override.
This lets an Eigen::Ref-returning function be bound with `rvp::copy`,
for example, to specify that the data should be copied into a new numpy
array rather than referenced, or `rvp::reference_internal` to indicate
that it should be referenced, but a keep-alive used (actually, we used
the array's `base` rather than a py::keep_alive in such a case, but it
accomplishes the same thing).
2017-01-20 05:59:26 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-09-11 16:17:41 +00:00
|
|
|
// Basic python -> C++ casting; throws if casting fails
|
2024-07-20 06:55:22 +00:00
|
|
|
template <typename T, typename SFINAE>
|
|
|
|
type_caster<T, SFINAE> &load_type(type_caster<T, SFINAE> &conv, const handle &handle) {
|
2022-05-16 20:51:01 +00:00
|
|
|
static_assert(!detail::is_pyobject<T>::value,
|
|
|
|
"Internal error: type_caster should only be used for C++ types");
|
2016-07-01 14:07:24 +00:00
|
|
|
if (!conv.load(handle, true)) {
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
2023-02-10 05:21:17 +00:00
|
|
|
throw cast_error(
|
|
|
|
"Unable to cast Python instance of type "
|
|
|
|
+ str(type::handle_of(handle)).cast<std::string>()
|
|
|
|
+ " to C++ type '?' (#define "
|
|
|
|
"PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)");
|
2016-07-01 14:07:24 +00:00
|
|
|
#else
|
2022-02-10 20:17:07 +00:00
|
|
|
throw cast_error("Unable to cast Python instance of type "
|
2023-02-10 05:21:17 +00:00
|
|
|
+ str(type::handle_of(handle)).cast<std::string>() + " to C++ type '"
|
2022-02-10 20:17:07 +00:00
|
|
|
+ type_id<T>() + "'");
|
2016-07-01 14:07:24 +00:00
|
|
|
#endif
|
|
|
|
}
|
2016-09-08 18:49:43 +00:00
|
|
|
return conv;
|
|
|
|
}
|
2016-09-11 16:17:41 +00:00
|
|
|
// Wrapper around the above that also constructs and returns a type_caster
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
make_caster<T> load_type(const handle &handle) {
|
2016-09-11 16:17:41 +00:00
|
|
|
make_caster<T> conv;
|
|
|
|
load_type(conv, handle);
|
|
|
|
return conv;
|
|
|
|
}
|
2016-09-08 18:49:43 +00:00
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_END(detail)
|
2016-09-08 18:49:43 +00:00
|
|
|
|
2016-10-28 01:08:15 +00:00
|
|
|
// pytype -> C++ type
|
Add `type_caster<PyObject>` (#4601)
* Add `type_caster<PyObject>` (tests are still incomplete).
* Fix oversight (`const PyObject *`).
* Ensure `type_caster<PyObject>` only works for `PyObject *`
* Move `is_same_ignoring_cvref` into `detail` namespace.
* Add test_cast_nullptr
* Change is_same_ignoring_cvref from variable template to using.
```
test_type_caster_pyobject_ptr.cpp:8:23: error: variable templates only available with ‘-std=c++14’ or ‘-std=gnu++14’ [-Werror]
8 | static constexpr bool is_same_ignoring_cvref = std::is_same<detail::remove_cvref_t<T>, U>::value;
| ^~~~~~~~~~~~~~~~~~~~~~
```
* Remove `return_value_policy::reference_internal` `keep_alive` feature (because of doubts about it actually being useful).
* Add missing test, fix bug (missing `throw error_already_set();`), various cosmetic changes.
* Move `type_caster<PyObject>` from test to new include (pybind11/type_caster_pyobject_ptr.h)
* Add new header file to CMakeLists.txt and tests/extra_python_package/test_files.py
* Backport changes from https://github.com/google/pywrapcc/pull/30021 to https://github.com/pybind/pybind11/pull/4601
* Fix oversight in test (to resolve a valgrind leak detection error) and add a related comment in cast.h.
No production code changes.
Make tests more sensitive by using `ValueHolder` instead of empty tuples and dicts.
Manual leak checks with `while True:` & top command repeated for all tests.
* Add tests for interop with stl.h `list_caster`
(No production code changes.)
* Bug fix in test. Minor comment enhancements.
* Change `type_caster<PyObject>::name` to `object`, as suggested by @Skylion007
* Expand comment for the new `T cast(const handle &handle)` [`T` = `PyObject *`]
* Add `T cast(object &&obj)` overload as suggested by @Skylion007
The original suggestion leads to `error: call to 'cast' is ambiguous` (full error message below), therefore SFINAE guarding is needed.
```
clang++ -o pybind11/tests/test_type_caster_pyobject_ptr.os -c -std=c++17 -fPIC -fvisibility=hidden -O0 -g -Wall -Wextra -Wconversion -Wcast-qual -Wdeprecated -Wundef -Wnon-virtual-dtor -Wunused-result -Werror -isystem /usr/include/python3.10 -isystem /usr/include/eigen3 -DPYBIND11_STRICT_ASSERTS_CLASS_HOLDER_VS_TYPE_CASTER_MIX -DPYBIND11_ENABLE_TYPE_CASTER_ODR_GUARD_IF_AVAILABLE -DPYBIND11_TEST_BOOST -Ipybind11/include -I/usr/local/google/home/rwgk/forked/pybind11/include -I/usr/local/google/home/rwgk/clone/pybind11/include /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp
In file included from /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:1:
In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/functional.h:12:
In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:13:
In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/detail/class.h:12:
In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/attr.h:14:
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1165:12: error: call to 'cast' is ambiguous
return pybind11::cast<T>(std::move(*this));
^~~~~~~~~~~~~~~~~
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/functional.h:109:70: note: in instantiation of function template specialization 'pybind11::object::cast<_object *>' requested here
return hfunc.f(std::forward<Args>(args)...).template cast<Return>();
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/functional.h:103:16: note: in instantiation of member function 'pybind11::detail::type_caster<std::function<_object *(int)>>::load(pybind11::handle, bool)::func_wrapper::operator()' requested here
struct func_wrapper {
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1456:47: note: in instantiation of member function 'pybind11::detail::type_caster<std::function<_object *(int)>>::load' requested here
if ((... || !std::get<Is>(argcasters).load(call.args[Is], call.args_convert[Is]))) {
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1434:50: note: in instantiation of function template specialization 'pybind11::detail::argument_loader<const std::function<_object *(int)> &, int>::load_impl_sequence<0UL, 1UL>' requested here
bool load_args(function_call &call) { return load_impl_sequence(call, indices{}); }
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:227:33: note: in instantiation of member function 'pybind11::detail::argument_loader<const std::function<_object *(int)> &, int>::load_args' requested here
if (!args_converter.load_args(call)) {
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:101:9: note: in instantiation of function template specialization 'pybind11::cpp_function::initialize<(lambda at /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:50:9), _object *, const std::function<_object *(int)> &, int, pybind11::name, pybind11::scope, pybind11::sibling, pybind11::return_value_policy>' requested here
initialize(
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:1163:22: note: in instantiation of function template specialization 'pybind11::cpp_function::cpp_function<(lambda at /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:50:9), pybind11::name, pybind11::scope, pybind11::sibling, pybind11::return_value_policy, void>' requested here
cpp_function func(std::forward<Func>(f),
^
/usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:48:7: note: in instantiation of function template specialization 'pybind11::module_::def<(lambda at /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:50:9), pybind11::return_value_policy>' requested here
m.def(
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1077:3: note: candidate function [with T = _object *, $1 = 0]
T cast(object &&obj) {
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1149:1: note: candidate function [with T = _object *]
cast(object &&object) {
^
1 error generated.
```
2023-05-07 17:15:53 +00:00
|
|
|
template <typename T,
|
|
|
|
detail::enable_if_t<!detail::is_pyobject<T>::value
|
|
|
|
&& !detail::is_same_ignoring_cvref<T, PyObject *>::value,
|
|
|
|
int>
|
|
|
|
= 0>
|
2016-10-25 20:12:39 +00:00
|
|
|
T cast(const handle &handle) {
|
2016-11-25 17:35:00 +00:00
|
|
|
using namespace detail;
|
2024-07-31 21:06:39 +00:00
|
|
|
constexpr bool is_enum_cast = type_uses_type_caster_enum_type<intrinsic_t<T>>::value;
|
|
|
|
static_assert(!cast_is_temporary_value_reference<T>::value || is_enum_cast,
|
2022-02-10 20:17:07 +00:00
|
|
|
"Unable to cast type to reference: value is local to type caster");
|
2024-07-31 21:06:39 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
if (is_enum_cast && cast_is_temporary_value_reference<T>::value) {
|
|
|
|
if (detail::global_internals_native_enum_type_map_contains(
|
|
|
|
std::type_index(typeid(intrinsic_t<T>)))) {
|
|
|
|
pybind11_fail("Unable to cast native enum type to reference");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2016-11-25 17:35:00 +00:00
|
|
|
return cast_op<T>(load_type<T>(handle));
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2016-10-28 01:08:15 +00:00
|
|
|
// pytype -> pytype (calls converting constructor)
|
2016-10-25 20:12:39 +00:00
|
|
|
template <typename T, detail::enable_if_t<detail::is_pyobject<T>::value, int> = 0>
|
2022-02-10 20:17:07 +00:00
|
|
|
T cast(const handle &handle) {
|
|
|
|
return T(reinterpret_borrow<object>(handle));
|
|
|
|
}
|
2016-10-25 20:12:39 +00:00
|
|
|
|
Add `type_caster<PyObject>` (#4601)
* Add `type_caster<PyObject>` (tests are still incomplete).
* Fix oversight (`const PyObject *`).
* Ensure `type_caster<PyObject>` only works for `PyObject *`
* Move `is_same_ignoring_cvref` into `detail` namespace.
* Add test_cast_nullptr
* Change is_same_ignoring_cvref from variable template to using.
```
test_type_caster_pyobject_ptr.cpp:8:23: error: variable templates only available with ‘-std=c++14’ or ‘-std=gnu++14’ [-Werror]
8 | static constexpr bool is_same_ignoring_cvref = std::is_same<detail::remove_cvref_t<T>, U>::value;
| ^~~~~~~~~~~~~~~~~~~~~~
```
* Remove `return_value_policy::reference_internal` `keep_alive` feature (because of doubts about it actually being useful).
* Add missing test, fix bug (missing `throw error_already_set();`), various cosmetic changes.
* Move `type_caster<PyObject>` from test to new include (pybind11/type_caster_pyobject_ptr.h)
* Add new header file to CMakeLists.txt and tests/extra_python_package/test_files.py
* Backport changes from https://github.com/google/pywrapcc/pull/30021 to https://github.com/pybind/pybind11/pull/4601
* Fix oversight in test (to resolve a valgrind leak detection error) and add a related comment in cast.h.
No production code changes.
Make tests more sensitive by using `ValueHolder` instead of empty tuples and dicts.
Manual leak checks with `while True:` & top command repeated for all tests.
* Add tests for interop with stl.h `list_caster`
(No production code changes.)
* Bug fix in test. Minor comment enhancements.
* Change `type_caster<PyObject>::name` to `object`, as suggested by @Skylion007
* Expand comment for the new `T cast(const handle &handle)` [`T` = `PyObject *`]
* Add `T cast(object &&obj)` overload as suggested by @Skylion007
The original suggestion leads to `error: call to 'cast' is ambiguous` (full error message below), therefore SFINAE guarding is needed.
```
clang++ -o pybind11/tests/test_type_caster_pyobject_ptr.os -c -std=c++17 -fPIC -fvisibility=hidden -O0 -g -Wall -Wextra -Wconversion -Wcast-qual -Wdeprecated -Wundef -Wnon-virtual-dtor -Wunused-result -Werror -isystem /usr/include/python3.10 -isystem /usr/include/eigen3 -DPYBIND11_STRICT_ASSERTS_CLASS_HOLDER_VS_TYPE_CASTER_MIX -DPYBIND11_ENABLE_TYPE_CASTER_ODR_GUARD_IF_AVAILABLE -DPYBIND11_TEST_BOOST -Ipybind11/include -I/usr/local/google/home/rwgk/forked/pybind11/include -I/usr/local/google/home/rwgk/clone/pybind11/include /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp
In file included from /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:1:
In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/functional.h:12:
In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:13:
In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/detail/class.h:12:
In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/attr.h:14:
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1165:12: error: call to 'cast' is ambiguous
return pybind11::cast<T>(std::move(*this));
^~~~~~~~~~~~~~~~~
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/functional.h:109:70: note: in instantiation of function template specialization 'pybind11::object::cast<_object *>' requested here
return hfunc.f(std::forward<Args>(args)...).template cast<Return>();
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/functional.h:103:16: note: in instantiation of member function 'pybind11::detail::type_caster<std::function<_object *(int)>>::load(pybind11::handle, bool)::func_wrapper::operator()' requested here
struct func_wrapper {
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1456:47: note: in instantiation of member function 'pybind11::detail::type_caster<std::function<_object *(int)>>::load' requested here
if ((... || !std::get<Is>(argcasters).load(call.args[Is], call.args_convert[Is]))) {
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1434:50: note: in instantiation of function template specialization 'pybind11::detail::argument_loader<const std::function<_object *(int)> &, int>::load_impl_sequence<0UL, 1UL>' requested here
bool load_args(function_call &call) { return load_impl_sequence(call, indices{}); }
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:227:33: note: in instantiation of member function 'pybind11::detail::argument_loader<const std::function<_object *(int)> &, int>::load_args' requested here
if (!args_converter.load_args(call)) {
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:101:9: note: in instantiation of function template specialization 'pybind11::cpp_function::initialize<(lambda at /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:50:9), _object *, const std::function<_object *(int)> &, int, pybind11::name, pybind11::scope, pybind11::sibling, pybind11::return_value_policy>' requested here
initialize(
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:1163:22: note: in instantiation of function template specialization 'pybind11::cpp_function::cpp_function<(lambda at /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:50:9), pybind11::name, pybind11::scope, pybind11::sibling, pybind11::return_value_policy, void>' requested here
cpp_function func(std::forward<Func>(f),
^
/usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:48:7: note: in instantiation of function template specialization 'pybind11::module_::def<(lambda at /usr/local/google/home/rwgk/forked/pybind11/tests/test_type_caster_pyobject_ptr.cpp:50:9), pybind11::return_value_policy>' requested here
m.def(
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1077:3: note: candidate function [with T = _object *, $1 = 0]
T cast(object &&obj) {
^
/usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:1149:1: note: candidate function [with T = _object *]
cast(object &&object) {
^
1 error generated.
```
2023-05-07 17:15:53 +00:00
|
|
|
// Note that `cast<PyObject *>(obj)` increments the reference count of `obj`.
|
|
|
|
// This is necessary for the case that `obj` is a temporary, and could
|
|
|
|
// not possibly be different, given
|
|
|
|
// 1. the established convention that the passed `handle` is borrowed, and
|
|
|
|
// 2. we don't want to force all generic code using `cast<T>()` to special-case
|
|
|
|
// handling of `T` = `PyObject *` (to increment the reference count there).
|
|
|
|
// It is the responsibility of the caller to ensure that the reference count
|
|
|
|
// is decremented.
|
|
|
|
template <typename T,
|
|
|
|
typename Handle,
|
|
|
|
detail::enable_if_t<detail::is_same_ignoring_cvref<T, PyObject *>::value
|
|
|
|
&& detail::is_same_ignoring_cvref<Handle, handle>::value,
|
|
|
|
int>
|
|
|
|
= 0>
|
|
|
|
T cast(Handle &&handle) {
|
|
|
|
return handle.inc_ref().ptr();
|
|
|
|
}
|
|
|
|
// To optimize way an inc_ref/dec_ref cycle:
|
|
|
|
template <typename T,
|
|
|
|
typename Object,
|
|
|
|
detail::enable_if_t<detail::is_same_ignoring_cvref<T, PyObject *>::value
|
|
|
|
&& detail::is_same_ignoring_cvref<Object, object>::value,
|
|
|
|
int>
|
|
|
|
= 0>
|
|
|
|
T cast(Object &&obj) {
|
|
|
|
return obj.release().ptr();
|
|
|
|
}
|
|
|
|
|
2016-10-28 01:08:15 +00:00
|
|
|
// C++ type -> py::object
|
2016-10-25 20:12:39 +00:00
|
|
|
template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> = 0>
|
2022-02-10 20:17:07 +00:00
|
|
|
object cast(T &&value,
|
|
|
|
return_value_policy policy = return_value_policy::automatic_reference,
|
2016-10-25 20:12:39 +00:00
|
|
|
handle parent = handle()) {
|
2020-06-30 23:53:09 +00:00
|
|
|
using no_ref_T = typename std::remove_reference<T>::type;
|
2022-02-08 00:23:20 +00:00
|
|
|
if (policy == return_value_policy::automatic) {
|
2022-02-10 20:17:07 +00:00
|
|
|
policy = std::is_pointer<no_ref_T>::value ? return_value_policy::take_ownership
|
|
|
|
: std::is_lvalue_reference<T>::value ? return_value_policy::copy
|
|
|
|
: return_value_policy::move;
|
2022-02-08 00:23:20 +00:00
|
|
|
} else if (policy == return_value_policy::automatic_reference) {
|
|
|
|
policy = std::is_pointer<no_ref_T>::value ? return_value_policy::reference
|
|
|
|
: std::is_lvalue_reference<T>::value ? return_value_policy::copy
|
|
|
|
: return_value_policy::move;
|
|
|
|
}
|
2022-02-10 20:17:07 +00:00
|
|
|
return reinterpret_steal<object>(
|
|
|
|
detail::make_caster<T>::cast(std::forward<T>(value), policy, parent));
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
T handle::cast() const {
|
|
|
|
return pybind11::cast<T>(*this);
|
|
|
|
}
|
|
|
|
template <>
|
|
|
|
inline void handle::cast() const {
|
|
|
|
return;
|
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
template <typename T>
|
Change all_of_t/any_of_t to all_of/any_of, add none_of
This replaces the current `all_of_t<Pred, Ts...>` with `all_of<Ts...>`,
with previous use of `all_of_t<Pred, Ts...>` becoming
`all_of<Pred<Ts>...>` (and similarly for `any_of_t`). It also adds a
`none_of<Ts...>`, a shortcut for `negation<any_of<Ts...>>`.
This allows `all_of` and `any_of` to be used a bit more flexible, e.g.
in cases where several predicates need to be tested for the same type
instead of the same predicate for multiple types.
This commit replaces the implementation with a more efficient version
for non-MSVC. For MSVC, this changes the workaround to use the
built-in, recursive std::conjunction/std::disjunction instead.
This also removes the `count_t` since `any_of_t` and `all_of_t` were the
only things using it.
This commit also rearranges some of the future std imports to use actual
`std` implementations for C++14/17 features when under the appropriate
compiler mode, as we were already doing for a few things (like
index_sequence). Most of these aren't saving much (the implementation
for enable_if_t, for example, is trivial), but I think it makes the
intention of the code instantly clear. It also enables MSVC's native
std::index_sequence support.
2016-12-12 23:11:49 +00:00
|
|
|
detail::enable_if_t<!detail::move_never<T>::value, T> move(object &&obj) {
|
2022-02-08 00:17:32 +00:00
|
|
|
if (obj.ref_count() > 1) {
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
2022-02-10 20:17:07 +00:00
|
|
|
throw cast_error(
|
2023-02-10 05:21:17 +00:00
|
|
|
"Unable to cast Python " + str(type::handle_of(obj)).cast<std::string>()
|
|
|
|
+ " instance to C++ rvalue: instance has multiple references"
|
|
|
|
" (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)");
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
#else
|
2023-02-10 05:21:17 +00:00
|
|
|
throw cast_error("Unable to move from Python "
|
|
|
|
+ str(type::handle_of(obj)).cast<std::string>() + " instance to C++ "
|
|
|
|
+ type_id<T>() + " instance: instance has multiple references");
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
#endif
|
2022-02-08 00:17:32 +00:00
|
|
|
}
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
|
|
|
|
// Move into a temporary and return that, because the reference may be a local value of `conv`
|
2022-02-10 20:17:07 +00:00
|
|
|
T ret = std::move(detail::load_type<T>(obj).operator T &());
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-08-21 19:27:21 +00:00
|
|
|
// Calling cast() on an rvalue calls pybind11::cast with the object rvalue, which does:
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
// - If we have to move (because T has no copy constructor), do it. This will fail if the moved
|
|
|
|
// object has multiple references, but trying to copy will fail to compile.
|
|
|
|
// - If both movable and copyable, check ref count: if 1, move; otherwise copy
|
|
|
|
// - Otherwise (not movable), copy.
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
2022-05-16 20:51:01 +00:00
|
|
|
detail::enable_if_t<!detail::is_pyobject<T>::value && detail::move_always<T>::value, T>
|
|
|
|
cast(object &&object) {
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
return move<T>(std::move(object));
|
|
|
|
}
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
2022-05-16 20:51:01 +00:00
|
|
|
detail::enable_if_t<!detail::is_pyobject<T>::value && detail::move_if_unreferenced<T>::value, T>
|
|
|
|
cast(object &&object) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (object.ref_count() > 1) {
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
return cast<T>(object);
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2021-07-09 13:45:53 +00:00
|
|
|
return move<T>(std::move(object));
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
}
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
2022-05-16 20:51:01 +00:00
|
|
|
detail::enable_if_t<!detail::is_pyobject<T>::value && detail::move_never<T>::value, T>
|
|
|
|
cast(object &&object) {
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
return cast<T>(object);
|
|
|
|
}
|
|
|
|
|
2022-05-16 20:51:01 +00:00
|
|
|
// pytype rvalue -> pytype (calls converting constructor)
|
|
|
|
template <typename T>
|
|
|
|
detail::enable_if_t<detail::is_pyobject<T>::value, T> cast(object &&object) {
|
|
|
|
return T(std::move(object));
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
T object::cast() const & {
|
|
|
|
return pybind11::cast<T>(*this);
|
|
|
|
}
|
|
|
|
template <typename T>
|
|
|
|
T object::cast() && {
|
|
|
|
return pybind11::cast<T>(std::move(*this));
|
|
|
|
}
|
|
|
|
template <>
|
|
|
|
inline void object::cast() const & {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
template <>
|
|
|
|
inline void object::cast() && {
|
|
|
|
return;
|
|
|
|
}
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
2016-09-08 18:49:43 +00:00
|
|
|
|
2016-12-12 22:42:52 +00:00
|
|
|
// Declared in pytypes.h:
|
|
|
|
template <typename T, enable_if_t<!is_pyobject<T>::value, int>>
|
2022-02-10 20:17:07 +00:00
|
|
|
object object_or_cast(T &&o) {
|
|
|
|
return pybind11::cast(std::forward<T>(o));
|
|
|
|
}
|
2016-12-12 22:42:52 +00:00
|
|
|
|
2022-02-10 19:42:03 +00:00
|
|
|
// Placeholder type for the unneeded (and dead code) static variable in the
|
|
|
|
// PYBIND11_OVERRIDE_OVERRIDE macro
|
|
|
|
struct override_unused {};
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename ret_type>
|
|
|
|
using override_caster_t = conditional_t<cast_is_temporary_value_reference<ret_type>::value,
|
|
|
|
make_caster<ret_type>,
|
|
|
|
override_unused>;
|
2016-09-08 18:49:43 +00:00
|
|
|
|
|
|
|
// Trampoline use: for reference/pointer types to value-converted values, we do a value cast, then
|
|
|
|
// store the result in the given variable. For other types, this is a no-op.
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&o,
|
|
|
|
make_caster<T> &caster) {
|
2016-11-25 17:35:00 +00:00
|
|
|
return cast_op<T>(load_type(caster, o));
|
2016-09-08 18:49:43 +00:00
|
|
|
}
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&,
|
|
|
|
override_unused &) {
|
|
|
|
pybind11_fail("Internal error: cast_ref fallback invoked");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Trampoline use: Having a pybind11::cast with an invalid reference type is going to
|
|
|
|
// static_assert, even though if it's in dead code, so we provide a "trampoline" to pybind11::cast
|
|
|
|
// that only does anything in cases where pybind11::cast is valid.
|
|
|
|
template <typename T>
|
2024-06-11 21:00:52 +00:00
|
|
|
enable_if_t<cast_is_temporary_value_reference<T>::value
|
|
|
|
&& !detail::is_same_ignoring_cvref<T, PyObject *>::value,
|
|
|
|
T>
|
|
|
|
cast_safe(object &&) {
|
2022-02-10 20:17:07 +00:00
|
|
|
pybind11_fail("Internal error: cast_safe fallback invoked");
|
|
|
|
}
|
2022-04-11 18:57:05 +00:00
|
|
|
template <typename T>
|
2022-10-22 23:52:35 +00:00
|
|
|
enable_if_t<std::is_void<T>::value, void> cast_safe(object &&) {}
|
2022-04-11 18:57:05 +00:00
|
|
|
template <typename T>
|
2024-06-11 21:00:52 +00:00
|
|
|
enable_if_t<detail::is_same_ignoring_cvref<T, PyObject *>::value, PyObject *>
|
|
|
|
cast_safe(object &&o) {
|
|
|
|
return o.release().ptr();
|
|
|
|
}
|
|
|
|
template <typename T>
|
|
|
|
enable_if_t<detail::none_of<cast_is_temporary_value_reference<T>,
|
|
|
|
detail::is_same_ignoring_cvref<T, PyObject *>,
|
|
|
|
std::is_void<T>>::value,
|
|
|
|
T>
|
2022-04-11 18:57:05 +00:00
|
|
|
cast_safe(object &&o) {
|
|
|
|
return pybind11::cast<T>(std::move(o));
|
|
|
|
}
|
2016-09-08 18:49:43 +00:00
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_END(detail)
|
Move support for return values of called Python functions
Currently pybind11 always translates values returned by Python functions
invoked from C++ code by copying, even when moving is feasible--and,
more importantly, even when moving is required.
The first, and relatively minor, concern is that moving may be
considerably more efficient for some types. The second problem,
however, is more serious: there's currently no way python code can
return a non-copyable type to C++ code.
I ran into this while trying to add a PYBIND11_OVERLOAD of a virtual
method that returns just such a type: it simply fails to compile because
this:
overload = ...
overload(args).template cast<ret_type>();
involves a copy: overload(args) returns an object instance, and the
invoked object::cast() loads the returned value, then returns a copy of
the loaded value.
We can, however, safely move that returned value *if* the object has the
only reference to it (i.e. if ref_count() == 1) and the object is
itself temporary (i.e. if it's an rvalue).
This commit does that by adding an rvalue-qualified object::cast()
method that allows the returned value to be move-constructed out of the
stored instance when feasible.
This basically comes down to three cases:
- For objects that are movable but not copyable, we always try the move,
with a runtime exception raised if this would involve moving a value
with multiple references.
- When the type is both movable and non-trivially copyable, the move
happens only if the invoked object has a ref_count of 1, otherwise the
object is copied. (Trivially copyable types are excluded from this
case because they are typically just collections of primitive types,
which can be copied just as easily as they can be moved.)
- Non-movable and trivially copy constructible objects are simply
copied.
This also adds examples to example-virtual-functions that shows both a
non-copyable object and a movable/copyable object in action: the former
raises an exception if returned while holding a reference, the latter
invokes a move constructor if unreferenced, or a copy constructor if
referenced.
Basically this allows code such as:
class MyClass(Pybind11Class):
def somemethod(self, whatever):
mt = MovableType(whatever)
# ...
return mt
which allows the MovableType instance to be returned to the C++ code
via its move constructor.
Of course if you attempt to violate this by doing something like:
self.value = MovableType(whatever)
return self.value
you get an exception--but right now, the pybind11-side of that code
won't compile at all.
2016-07-22 01:31:05 +00:00
|
|
|
|
2021-07-06 22:13:13 +00:00
|
|
|
// The overloads could coexist, i.e. the #if is not strictly speaking needed,
|
|
|
|
// but it is an easy minor optimization.
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
2023-02-10 05:21:17 +00:00
|
|
|
inline cast_error cast_error_unable_to_convert_call_arg(const std::string &name) {
|
|
|
|
return cast_error("Unable to convert call argument '" + name
|
|
|
|
+ "' to Python object (#define "
|
|
|
|
"PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)");
|
2021-07-06 22:13:13 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
inline cast_error cast_error_unable_to_convert_call_arg(const std::string &name,
|
|
|
|
const std::string &type) {
|
|
|
|
return cast_error("Unable to convert call argument '" + name + "' of type '" + type
|
|
|
|
+ "' to Python object");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-02-06 14:40:50 +00:00
|
|
|
template <return_value_policy policy = return_value_policy::automatic_reference>
|
2022-02-10 20:17:07 +00:00
|
|
|
tuple make_tuple() {
|
|
|
|
return tuple(0);
|
|
|
|
}
|
2018-02-06 14:40:50 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args>
|
|
|
|
tuple make_tuple(Args &&...args_) {
|
2017-04-05 14:51:02 +00:00
|
|
|
constexpr size_t size = sizeof...(Args);
|
2022-02-10 20:17:07 +00:00
|
|
|
std::array<object, size> args{{reinterpret_steal<object>(
|
|
|
|
detail::make_caster<Args>::cast(std::forward<Args>(args_), policy, nullptr))...}};
|
2017-04-05 14:51:02 +00:00
|
|
|
for (size_t i = 0; i < args.size(); i++) {
|
|
|
|
if (!args[i]) {
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
2023-02-10 05:21:17 +00:00
|
|
|
throw cast_error_unable_to_convert_call_arg(std::to_string(i));
|
2016-07-01 18:35:35 +00:00
|
|
|
#else
|
2022-02-10 20:17:07 +00:00
|
|
|
std::array<std::string, size> argtypes{{type_id<Args>()...}};
|
2021-07-06 22:13:13 +00:00
|
|
|
throw cast_error_unable_to_convert_call_arg(std::to_string(i), argtypes[i]);
|
2016-07-01 18:35:35 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2016-04-12 22:56:17 +00:00
|
|
|
tuple result(size);
|
2015-07-05 18:05:44 +00:00
|
|
|
int counter = 0;
|
2022-02-08 00:23:20 +00:00
|
|
|
for (auto &arg_value : args) {
|
2016-04-12 22:56:17 +00:00
|
|
|
PyTuple_SET_ITEM(result.ptr(), counter++, arg_value.release().ptr());
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-04-12 22:56:17 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-01-31 15:54:08 +00:00
|
|
|
/// \ingroup annotations
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
/// Annotation for arguments
|
2016-09-05 22:49:21 +00:00
|
|
|
struct arg {
|
2022-02-10 20:17:07 +00:00
|
|
|
/// Constructs an argument with the name of the argument; if null or omitted, this is a
|
|
|
|
/// positional argument.
|
|
|
|
constexpr explicit arg(const char *name = nullptr)
|
|
|
|
: name(name), flag_noconvert(false), flag_none(true) {}
|
2017-01-31 15:54:08 +00:00
|
|
|
/// Assign a value to this argument
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
arg_v operator=(T &&value) const;
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
/// Indicate that the type should not be converted in the type caster
|
2022-02-10 20:17:07 +00:00
|
|
|
arg &noconvert(bool flag = true) {
|
|
|
|
flag_noconvert = flag;
|
|
|
|
return *this;
|
|
|
|
}
|
2017-05-17 15:55:43 +00:00
|
|
|
/// Indicates that the argument should/shouldn't allow None (e.g. for nullable pointer args)
|
2022-02-10 20:17:07 +00:00
|
|
|
arg &none(bool flag = true) {
|
|
|
|
flag_none = flag;
|
|
|
|
return *this;
|
|
|
|
}
|
2016-09-05 22:49:21 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
const char *name; ///< If non-null, this is a named kwargs argument
|
|
|
|
bool flag_noconvert : 1; ///< If set, do not allow conversion (requires a supporting type
|
|
|
|
///< caster!)
|
|
|
|
bool flag_none : 1; ///< If set (the default), allow None to be passed to this argument
|
2016-09-05 22:49:21 +00:00
|
|
|
};
|
|
|
|
|
2017-01-31 15:54:08 +00:00
|
|
|
/// \ingroup annotations
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
/// Annotation for arguments with values
|
2016-09-05 22:49:21 +00:00
|
|
|
struct arg_v : arg {
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
private:
|
2016-09-05 22:49:21 +00:00
|
|
|
template <typename T>
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
arg_v(arg &&base, T &&x, const char *descr = nullptr)
|
2022-04-05 18:36:39 +00:00
|
|
|
: arg(base), value(reinterpret_steal<object>(detail::make_caster<T>::cast(
|
|
|
|
std::forward<T>(x), return_value_policy::automatic, {}))),
|
2016-09-05 22:49:21 +00:00
|
|
|
descr(descr)
|
2022-05-02 19:30:19 +00:00
|
|
|
#if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
2022-02-10 20:17:07 +00:00
|
|
|
,
|
|
|
|
type(type_id<T>())
|
2016-09-05 22:49:21 +00:00
|
|
|
#endif
|
2020-11-23 19:02:25 +00:00
|
|
|
{
|
|
|
|
// Workaround! See:
|
|
|
|
// https://github.com/pybind/pybind11/issues/2336
|
|
|
|
// https://github.com/pybind/pybind11/pull/2685#issuecomment-731286700
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
PyErr_Clear();
|
|
|
|
}
|
|
|
|
}
|
2016-09-05 22:49:21 +00:00
|
|
|
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
public:
|
|
|
|
/// Direct construction with name, default, and description
|
|
|
|
template <typename T>
|
|
|
|
arg_v(const char *name, T &&x, const char *descr = nullptr)
|
2022-02-10 20:17:07 +00:00
|
|
|
: arg_v(arg(name), std::forward<T>(x), descr) {}
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
|
|
|
|
/// Called internally when invoking `py::arg("a") = value`
|
|
|
|
template <typename T>
|
|
|
|
arg_v(const arg &base, T &&x, const char *descr = nullptr)
|
2022-02-10 20:17:07 +00:00
|
|
|
: arg_v(arg(base), std::forward<T>(x), descr) {}
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
|
|
|
|
/// Same as `arg::noconvert()`, but returns *this as arg_v&, not arg&
|
2022-02-10 20:17:07 +00:00
|
|
|
arg_v &noconvert(bool flag = true) {
|
|
|
|
arg::noconvert(flag);
|
|
|
|
return *this;
|
|
|
|
}
|
2017-05-17 15:55:43 +00:00
|
|
|
|
|
|
|
/// Same as `arg::nonone()`, but returns *this as arg_v&, not arg&
|
2022-02-10 20:17:07 +00:00
|
|
|
arg_v &none(bool flag = true) {
|
|
|
|
arg::none(flag);
|
|
|
|
return *this;
|
|
|
|
}
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
|
|
|
|
/// The default value
|
2016-09-05 22:49:21 +00:00
|
|
|
object value;
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
/// The (optional) description of the default value
|
2016-09-05 22:49:21 +00:00
|
|
|
const char *descr;
|
2022-05-02 19:30:19 +00:00
|
|
|
#if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
/// The C++ type name of the default value (only available when compiled in debug mode)
|
2016-09-05 22:49:21 +00:00
|
|
|
std::string type;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2017-12-23 22:56:07 +00:00
|
|
|
/// \ingroup annotations
|
2022-02-10 20:17:07 +00:00
|
|
|
/// Annotation indicating that all following arguments are keyword-only; the is the equivalent of
|
2022-02-11 02:28:08 +00:00
|
|
|
/// an unnamed '*' argument
|
2020-09-05 00:02:05 +00:00
|
|
|
struct kw_only {};
|
|
|
|
|
|
|
|
/// \ingroup annotations
|
2022-02-10 20:17:07 +00:00
|
|
|
/// Annotation indicating that all previous arguments are positional-only; the is the equivalent of
|
feat: remove Python 3.7 support (#5191)
* First pass updating misc files, informed by https://github.com/pybind/pybind11/pull/5177/commits
* Remove jobs using silkeh/clang and gcc docker containers that come with Python 3.7
* Add silkeh/clang:17-bookworm
* Add job using GCC 7
* Revert "Add job using GCC 7"
This reverts commit 518515a761ac37dc2cf5d0980da82d0de39edc28.
* Try running in ubuntu-18.04 container under ubuntu-latest (to get GCC 7)
* Fix `-` vs `:` mixup.
* This reverts commit b1c4304475b8ad129c12330c7ed7eb85d15ba14a.
Revert "Try running in ubuntu:18.04 container under ubuntu-latest (to get GCC 7)"
This reverts commit b203a294bb444fc6ae57a0100fa91dc91b8d3264.
* `git grep 0x03080000` cleanup.
* `git grep -I -E '3\.7'` cleanup.
Removes two changes made under pybind/pybind11#3702
* Revert "`git grep -I -E '3\.7'` cleanup."
This reverts commit bb5b9d187bffbfb61e2977d7eee46b766fa1cce9.
* Remove comments that are evidently incorrect:
```
...
-- The CXX compiler identification is Clang 15.0.7
...
- Found Python: /usr/bin/python3.9 (found suitable version "3.9.2", minimum required is "3.7") found components: Interpreter Development.Module Development.Embed
...
/__w/pybind11/pybind11/include/pybind11/gil.h:150:13: error: 'auto key' can be declared as 'auto *key' [readability-qualified-auto,-warnings-as-errors]
auto key = internals.tstate;
^~~~~
auto *
/__w/pybind11/pybind11/include/pybind11/gil.h:174:13: error: 'auto key' can be declared as 'auto *key' [readability-qualified-auto,-warnings-as-errors]
auto key = detail::get_internals().tstate;
^~~~~
auto *
```
* .github/workflows/configure.yml: Change from Python 3.7 to 3.8
* Misc cleanup pass
* Miscellaneous changes based on manual review of the `git grep` matches below:
```
git_grep_37_38.sh |& sort | uniq -c
```
With git_grep_37_38.sh:
```
set -x
git grep 0x0307
git grep 0x0308
git grep PY_MINOR_VERSION
git grep PYPY_VERSION
git grep -I -E '3\.7'
git grep -I -E '3\.8'
git grep -I -E '\(3, 7'
git grep -I -E '\(3, 8'
git grep -I -E '3[^A-Za-z0-9.]+7'
git grep -I -E '3[^A-Za-z0-9.]+8'
```
Output:
```
1 .appveyor.yml: $env:CMAKE_INCLUDE_PATH = "eigen-3.3.7;$env:CMAKE_INCLUDE_PATH"
1 .appveyor.yml: 7z x eigen-3.3.7.zip -y > $null
1 .appveyor.yml: Start-FileDownload 'https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.zip'
1 CMakeLists.txt: # Bug in macOS CMake < 3.7 is unable to download catch
1 CMakeLists.txt: elseif(WINDOWS AND CMAKE_VERSION VERSION_LESS 3.8)
1 CMakeLists.txt: if(OSX AND CMAKE_VERSION VERSION_LESS 3.7)
1 CMakeLists.txt: message(WARNING "CMAKE 3.7+ needed on macOS to download catch, and newer HIGHLY recommended")
1 CMakeLists.txt: message(WARNING "CMAKE 3.8+ tested on Windows, previous versions untested")
1 CMakeLists.txt: # Only tested with 3.8+ in CI.
1 docs/advanced/functions.rst:Python 3.8 introduced a new positional-only argument syntax, using ``/`` in the
1 docs/changelog.rst:* Adapt pybind11 to a C API convention change in Python 3.8. `#1950
1 docs/changelog.rst:* Allow thread termination to be avoided during shutdown for CPython 3.7+ via
1 docs/changelog.rst: considered as conversion, consistent with Python 3.8+.
1 docs/changelog.rst: CPython 3.8 and 3.9 debug builds.
1 docs/changelog.rst:* Enum now has an ``__index__`` method on Python <3.8 too.
1 docs/changelog.rst: on Python 3.8. `#1780 <https://github.com/pybind/pybind11/pull/1780>`_.
1 docs/changelog.rst:* PyPy 3.10 support was added, PyPy 3.7 support was dropped.
2 docs/changelog.rst:* Support PyPy 7.3.7 and the PyPy3.8 beta. Test python-3.11 on PRs with the
1 docs/changelog.rst:* Use ``macos-13`` (Intel) for CI jobs for now (will drop Python 3.7 soon).
1 docs/changelog.rst:* Use new Python 3.7 Thread Specific Storage (TSS) implementation if available.
1 docs/compiling.rst: cmake -DPYBIND11_PYTHON_VERSION=3.8 ..
1 docs/compiling.rst: find_package(Python 3.8 COMPONENTS Interpreter Development REQUIRED)
1 docs/limitations.rst:- PyPy3 7.3.1 and 7.3.2 have issues with several tests on 32-bit Windows.
1 docs/requirements.txt:idna==3.7 \
1 + git grep 0x0307
1 + git grep 0x0308
1 + git grep -I -E '\(3, 7'
1 + git grep -I -E '3\.7'
1 + git grep -I -E '\(3, 8'
1 + git grep -I -E '3\.8'
1 + git grep -I -E '3[^A-Za-z0-9.]+7'
1 + git grep -I -E '3[^A-Za-z0-9.]+8'
1 + git grep PY_MINOR_VERSION
1 + git grep PYPY_VERSION
2 .github/workflows/ci.yml: - '3.8'
1 .github/workflows/ci.yml: - 3.8
1 .github/workflows/ci.yml: - name: Add Python 3.8
1 .github/workflows/ci.yml: - 'pypy-3.8'
2 .github/workflows/ci.yml: python: '3.8'
1 .github/workflows/ci.yml: - python: '3.8'
1 .github/workflows/ci.yml: - python: 3.8
1 .github/workflows/ci.yml: python: 'pypy-3.8'
1 .github/workflows/configure.yml: cmake: "3.8"
1 .github/workflows/configure.yml: name: 🐍 3.8 • CMake ${{ matrix.cmake }} • ${{ matrix.runs-on }}
1 .github/workflows/configure.yml: - name: Setup Python 3.8
1 .github/workflows/configure.yml: python-version: 3.8
1 .github/workflows/pip.yml: name: 🐍 3.8 • 📦 & 📦 tests • ubuntu-latest
1 .github/workflows/pip.yml: name: 🐍 3.8 • 📦 tests • windows-latest
2 .github/workflows/pip.yml: - name: Setup 🐍 3.8
2 .github/workflows/pip.yml: python-version: 3.8
2 include/pybind11/cast.h:#if !defined(PYPY_VERSION)
2 include/pybind11/cast.h:#if defined(PYPY_VERSION)
2 include/pybind11/cast.h: // PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
5 include/pybind11/detail/class.h:#if !defined(PYPY_VERSION)
1 include/pybind11/detail/class.h:#if defined(PYPY_VERSION)
1 include/pybind11/detail/class.h: // This was not needed before Python 3.8 (Python issue 35810)
1 include/pybind11/detail/common.h: && !defined(PYPY_VERSION) && !defined(PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF)
2 include/pybind11/detail/common.h:# error "PYTHON < 3.8 IS UNSUPPORTED. pybind11 v2.13 was the last to support Python 3.7."
1 include/pybind11/detail/common.h:#if defined(PYPY_VERSION) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
1 include/pybind11/detail/common.h:#if PY_VERSION_HEX < 0x03080000
1 include/pybind11/detail/common.h: = PYBIND11_TOSTRING(PY_MAJOR_VERSION) "." PYBIND11_TOSTRING(PY_MINOR_VERSION); \
1 include/pybind11/detail/internals.h: // called. PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does
1 include/pybind11/detail/internals.h:#if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION)
1 include/pybind11/detail/internals.h:// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
1 include/pybind11/detail/type_caster_base.h:#if defined(PYPY_VERSION)
1 include/pybind11/embed.h:# define PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX (0x03080000)
1 include/pybind11/embed.h:#if defined(PYPY_VERSION)
1 include/pybind11/eval.h: // globals if not yet present. Python 3.8 made PyRun_String behave
2 include/pybind11/eval.h:#if defined(PYPY_VERSION)
2 include/pybind11/eval.h: // was missing from PyPy3.8 7.3.7.
2 include/pybind11/gil.h: /// allowed during shutdown. Check _Py_IsFinalizing() on Python 3.7+, and
1 include/pybind11/pybind11.h:#if !defined(PYPY_VERSION)
4 include/pybind11/pybind11.h:#if !defined(PYPY_VERSION) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 9
1 include/pybind11/pytypes.h:#endif //! defined(PYPY_VERSION)
2 include/pybind11/pytypes.h:#if !defined(PYPY_VERSION)
1 include/pybind11/pytypes.h:# if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x07030a00
1 include/pybind11/pytypes.h:#ifdef PYPY_VERSION
1 include/pybind11/stl/filesystem.h:# if !defined(PYPY_VERSION)
2 pybind11/__init__.py:if sys.version_info < (3, 8):
2 pybind11/__init__.py: msg = "pybind11 does not support Python < 3.8. v2.13 was the last release supporting Python 3.7."
1 pyproject.toml:master.py-version = "3.8"
1 pyproject.toml:python_version = "3.8"
1 README.rst:lines of code and depend on Python (3.8+, or PyPy) and the C++
2 README.rst:- Python 3.8+, and PyPy3 7.3 are supported with an implementation-agnostic
1 setup.cfg: Programming Language :: Python :: 3.8
1 setup.cfg:python_requires = >=3.8
1 setup.py:# TODO: use literals & overload (typing extensions or Python 3.8)
1 tests/CMakeLists.txt:if(NOT CMAKE_VERSION VERSION_LESS 3.8)
2 tests/constructor_stats.h:#if defined(PYPY_VERSION)
1 tests/env.py: doesn't work on CPython 3.8.0 with pytest==3.3.2 on Ubuntu 18.04 (#2922).
1 tests/requirements.txt:build~=1.0; python_version>="3.8"
1 tests/requirements.txt:numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.8" and python_version<"3.10"
1 tests/requirements.txt:numpy~=1.23.0; python_version=="3.8" and platform_python_implementation=="PyPy"
1 tests/test_buffers.py: env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
1 tests/test_builtin_casters.py: # Before Python 3.8, `PyLong_AsLong` does not pick up on `obj.__index__`,
2 tests/test_builtin_casters.py: if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
4 tests/test_builtin_casters.py: # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
1 tests/test_callbacks.py: assert m.test_callback3(z.double) == "func(43) = 86"
2 tests/test_call_policies.cpp:#if !defined(PYPY_VERSION)
1 tests/test_chrono.py: diff = m.test_chrono_float_diff(43.789012, 1.123456)
1 tests/test_constants_and_functions.py: assert m.f3(86) == 89
1 tests/test_eigen_matrix.py: a_copy3[8, 1] = 11
1 tests/test_eigen_matrix.py: assert np.all(cornersc == np.array([[1.0, 3], [7, 9]]))
1 tests/test_eigen_matrix.py: assert np.all(cornersr == np.array([[1.0, 3], [7, 9]]))
1 tests/test_eigen_matrix.py: mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
1 tests/test_exceptions.py: if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6
2 tests/test_exceptions.py:@pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False)
1 tests/test_factory_constructors.py: assert [i.alive() for i in cstats] == [13, 7]
1 tests/test_kwargs_and_defaults.cpp:#ifdef PYPY_VERSION
1 tests/test_local_bindings.py: assert i1.get3() == 8
1 tests/test_methods_and_attributes.cpp:#if !defined(PYPY_VERSION)
1 tests/test_numpy_array.py: a = np.arange(3 * 7 * 2) + 1
1 tests/test_numpy_array.py: assert str(excinfo.value) == "cannot reshape array of size 42 into shape (3,7,1)"
2 tests/test_numpy_array.py: assert x.shape == (3, 7, 2)
2 tests/test_numpy_array.py: m.reshape_tuple(a, (3, 7, 1))
2 tests/test_numpy_array.py: x = m.reshape_tuple(a, (3, 7, 2))
1 tests/test_numpy_vectorize.py: assert np.isclose(m.vectorized_func3(np.array(3 + 7j)), [6 + 14j])
1 tests/test_pickling.cpp:#if !defined(PYPY_VERSION)
1 tests/test_pytypes.cpp:#if (defined(__APPLE__) && defined(__clang__)) || defined(PYPY_VERSION)
1 tests/test_smart_ptr.cpp: m.def("make_myobject3_1", []() { return new MyObject3(8); });
1 tests/test_smart_ptr.py: assert cstats.values() == ["MyObject3[9]", "MyObject3[8]", "MyObject3[9]"]
1 tests/test_stl_binders.py: assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 88])
1 tests/test_stl_binders.py: assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 88, 4])
1 tests/test_type_caster_pyobject_ptr.cpp:#if !defined(PYPY_VERSION) // It is not worth the trouble doing something special for PyPy.
1 tools/FindPythonLibsNew.cmake: set(PythonLibsNew_FIND_VERSION "3.8")
1 tools/JoinPaths.cmake:# https://docs.python.org/3.7/library/os.path.html#os.path.join
1 tools/pybind11NewTools.cmake: Python 3.8 REQUIRED COMPONENTS ${_pybind11_interp_component} ${_pybind11_dev_component}
1 tools/pybind11NewTools.cmake:# Python debug libraries expose slightly different objects before 3.8
1 tools/pybind11Tools.cmake: "3.12;3.11;3.10;3.9;3.8"
1 tools/pybind11Tools.cmake: if(NOT DEFINED PYPY_VERSION)
1 tools/pybind11Tools.cmake: message(STATUS "PYPY ${PYPY_VERSION} (Py ${PYTHON_VERSION})")
1 tools/pybind11Tools.cmake:# Python debug libraries expose slightly different objects before 3.8
1 tools/pybind11Tools.cmake: set(PYPY_VERSION
```
* Change `[tool.ruff]` `target-version` to `"py38"`, as suggested by @Skylion007
2024-07-30 16:18:35 +00:00
|
|
|
/// an unnamed '/' argument
|
2020-09-05 00:02:05 +00:00
|
|
|
struct pos_only {};
|
2017-12-23 22:56:07 +00:00
|
|
|
|
2016-09-05 22:49:21 +00:00
|
|
|
template <typename T>
|
2021-06-19 17:53:27 +00:00
|
|
|
arg_v arg::operator=(T &&value) const {
|
|
|
|
return {*this, std::forward<T>(value)};
|
|
|
|
}
|
2016-09-05 22:49:21 +00:00
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
/// Alias for backward compatibility -- to be removed in version 2.0
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename /*unused*/>
|
|
|
|
using arg_t = arg_v;
|
2016-09-05 22:49:21 +00:00
|
|
|
|
|
|
|
inline namespace literals {
|
2017-01-31 15:54:08 +00:00
|
|
|
/** \rst
|
|
|
|
String literal version of `arg`
|
|
|
|
\endrst */
|
2023-08-03 20:36:29 +00:00
|
|
|
constexpr arg
|
|
|
|
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5
|
|
|
|
operator"" _a // gcc 4.8.5 insists on having a space (hard error).
|
|
|
|
#else
|
|
|
|
operator""_a // clang 17 generates a deprecation warning if there is a space.
|
|
|
|
#endif
|
|
|
|
(const char *name, size_t) {
|
|
|
|
return arg(name);
|
|
|
|
}
|
2020-09-11 01:16:40 +00:00
|
|
|
} // namespace literals
|
2016-09-05 22:49:21 +00:00
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
2016-11-27 17:19:34 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
using is_kw_only = std::is_same<intrinsic_t<T>, kw_only>;
|
|
|
|
template <typename T>
|
|
|
|
using is_pos_only = std::is_same<intrinsic_t<T>, pos_only>;
|
feat: allow kw-only args after a py::args (#3402)
* Simply has_kw_only_args handling
This simplifies tracking the number of kw-only args by instead tracking
the number of positional arguments (which is really what we care about
everywhere this is used).
* Allow keyword-only arguments to follow py::args
This removes the constraint that py::args has to be last (or
second-last, with py::kwargs) and instead makes py::args imply
py::kw_only for any remaining arguments, allowing you to bind a function
that works the same way as a Python function such as:
def f(a, *args, b):
return a * b + sum(args)
f(10, 1, 2, 3, b=20) # == 206
With this change, you can bind such a function using:
m.def("f", [](int a, py::args args, int b) { /* ... */ },
"a"_a, "b"_a);
Or, to be more explicit about the keyword-only arguments:
m.def("g", [](int a, py::args args, int b) { /* ... */ },
"a"_a, py::kw_only{}, "b"_a);
(The only difference between the two is that the latter will fail at
binding time if the `kw_only{}` doesn't match the `py::args` position).
This doesn't affect backwards compatibility at all because, currently,
you can't have a py::args anywhere except the end/2nd-last.
* Take args/kwargs by const lvalue ref
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
2021-10-29 03:16:55 +00:00
|
|
|
|
2017-06-21 17:38:10 +00:00
|
|
|
// forward declaration (definition in attr.h)
|
2017-01-22 04:42:14 +00:00
|
|
|
struct function_record;
|
|
|
|
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
/// Internal data associated with a single function call
|
|
|
|
struct function_call {
|
2018-09-25 21:55:18 +00:00
|
|
|
function_call(const function_record &f, handle p); // Implementation in attr.h
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
|
|
|
|
/// The function data:
|
|
|
|
const function_record &func;
|
|
|
|
|
|
|
|
/// Arguments passed to the function:
|
|
|
|
std::vector<handle> args;
|
|
|
|
|
|
|
|
/// The `convert` value the arguments should be loaded with
|
|
|
|
std::vector<bool> args_convert;
|
|
|
|
|
2017-12-23 13:42:32 +00:00
|
|
|
/// Extra references for the optional `py::args` and/or `py::kwargs` arguments (which, if
|
|
|
|
/// present, are also in `args` but without a reference).
|
|
|
|
object args_ref, kwargs_ref;
|
|
|
|
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
/// The parent, if any
|
|
|
|
handle parent;
|
2017-09-04 11:49:19 +00:00
|
|
|
|
|
|
|
/// If this is a call to an initializer, this argument contains `self`
|
|
|
|
handle init_self;
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
};
|
|
|
|
|
2016-11-27 17:19:34 +00:00
|
|
|
/// Helper class which loads arguments for C++ functions called from Python
|
|
|
|
template <typename... Args>
|
|
|
|
class argument_loader {
|
2016-11-27 19:56:04 +00:00
|
|
|
using indices = make_index_sequence<sizeof...(Args)>;
|
2016-11-27 17:19:34 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename Arg>
|
|
|
|
using argument_is_args = std::is_same<intrinsic_t<Arg>, args>;
|
|
|
|
template <typename Arg>
|
|
|
|
using argument_is_kwargs = std::is_same<intrinsic_t<Arg>, kwargs>;
|
feat: allow kw-only args after a py::args (#3402)
* Simply has_kw_only_args handling
This simplifies tracking the number of kw-only args by instead tracking
the number of positional arguments (which is really what we care about
everywhere this is used).
* Allow keyword-only arguments to follow py::args
This removes the constraint that py::args has to be last (or
second-last, with py::kwargs) and instead makes py::args imply
py::kw_only for any remaining arguments, allowing you to bind a function
that works the same way as a Python function such as:
def f(a, *args, b):
return a * b + sum(args)
f(10, 1, 2, 3, b=20) # == 206
With this change, you can bind such a function using:
m.def("f", [](int a, py::args args, int b) { /* ... */ },
"a"_a, "b"_a);
Or, to be more explicit about the keyword-only arguments:
m.def("g", [](int a, py::args args, int b) { /* ... */ },
"a"_a, py::kw_only{}, "b"_a);
(The only difference between the two is that the latter will fail at
binding time if the `kw_only{}` doesn't match the `py::args` position).
This doesn't affect backwards compatibility at all because, currently,
you can't have a py::args anywhere except the end/2nd-last.
* Take args/kwargs by const lvalue ref
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
2021-10-29 03:16:55 +00:00
|
|
|
// Get kwargs argument position, or -1 if not present:
|
|
|
|
static constexpr auto kwargs_pos = constexpr_last<argument_is_kwargs, Args...>();
|
2017-01-23 00:15:12 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
static_assert(kwargs_pos == -1 || kwargs_pos == (int) sizeof...(Args) - 1,
|
|
|
|
"py::kwargs is only permitted as the last argument of a function");
|
Work around gcc 7 ICE
Current g++ 7 snapshot fails to compile pybind under -std=c++17 with:
```
$ make
[ 3%] Building CXX object tests/CMakeFiles/pybind11_tests.dir/pybind11_tests.cpp.o
In file included from /home/jagerman/src/pybind11/tests/pybind11_tests.h:2:0,
from /home/jagerman/src/pybind11/tests/pybind11_tests.cpp:10:
/home/jagerman/src/pybind11/include/pybind11/pybind11.h: In instantiation of 'pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...)::<lambda(pybind11::detail::function_record*, pybind11::handle, pybind11::handle, pybind11::handle)> [with Func = pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...), const Extra& ...) [with Return = int; Class = ConstructorStats; Arg = {}; Extra = {pybind11::name, pybind11::is_method, pybind11::sibling}]::<lambda(ConstructorStats*)>; Return = int; Args = {ConstructorStats*}; Extra = {pybind11::name, pybind11::is_method, pybind11::sibling}]':
/home/jagerman/src/pybind11/include/pybind11/pybind11.h:120:22: required from 'struct pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...), const Extra& ...) [with Return = int; Class = ConstructorStats; Arg = {}; Extra = {pybind11::name, pybind11::is_method, pybind11::sibling}]::<lambda(ConstructorStats*)>; Return = int; Args = {ConstructorStats*}; Extra = {pybind11::name, pybind11::is_method, pybind11::sibling}]::<lambda(struct pybind11::detail::function_record*, class pybind11::handle, class pybind11::handle, class pybind11::handle)>'
/home/jagerman/src/pybind11/include/pybind11/pybind11.h:120:19: required from 'void pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...), const Extra& ...) [with Return = int; Class = ConstructorStats; Arg = {}; Extra = {pybind11::name, pybind11::is_method, pybind11::sibling}]::<lambda(ConstructorStats*)>; Return = int; Args = {ConstructorStats*}; Extra = {pybind11::name, pybind11::is_method, pybind11::sibling}]'
/home/jagerman/src/pybind11/include/pybind11/pybind11.h:62:9: required from 'pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...), const Extra& ...) [with Return = int; Class = ConstructorStats; Arg = {}; Extra = {pybind11::name, pybind11::is_method, pybind11::sibling}]'
/home/jagerman/src/pybind11/include/pybind11/pybind11.h:984:22: required from 'pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(const char*, Func&&, const Extra& ...) [with Func = int (ConstructorStats::*)(); Extra = {}; type_ = ConstructorStats; options = {}]'
/home/jagerman/src/pybind11/tests/pybind11_tests.cpp:24:47: required from here
/home/jagerman/src/pybind11/include/pybind11/pybind11.h:147:9: sorry, unimplemented: unexpected AST of kind cleanup_stmt
};
^
/home/jagerman/src/pybind11/include/pybind11/pybind11.h:147:9: internal compiler error: in potential_constant_expression_1, at cp/constexpr.c:5593
0x84c52a potential_constant_expression_1
../../src/gcc/cp/constexpr.c:5593
0x84c3c0 potential_constant_expression_1
../../src/gcc/cp/constexpr.c:5154
0x645511 finish_function(int)
../../src/gcc/cp/decl.c:15527
0x66e80b instantiate_decl(tree_node*, int, bool)
../../src/gcc/cp/pt.c:22558
0x6b61e2 instantiate_class_template_1
../../src/gcc/cp/pt.c:10444
0x6b61e2 instantiate_class_template(tree_node*)
../../src/gcc/cp/pt.c:10514
0x75a676 complete_type(tree_node*)
../../src/gcc/cp/typeck.c:133
0x67d5a4 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool)
../../src/gcc/cp/pt.c:17516
0x67ca19 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool)
../../src/gcc/cp/pt.c:16655
0x672cce tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool)
../../src/gcc/cp/pt.c:16140
0x6713dc tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool)
../../src/gcc/cp/pt.c:15408
0x671915 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool)
../../src/gcc/cp/pt.c:15394
0x671fc0 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool)
../../src/gcc/cp/pt.c:15618
0x66e97f tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool)
../../src/gcc/cp/pt.c:15379
0x66e97f instantiate_decl(tree_node*, int, bool)
../../src/gcc/cp/pt.c:22536
0x6ba0cb instantiate_pending_templates(int)
../../src/gcc/cp/pt.c:22653
0x6fd7f8 c_parse_final_cleanups()
../../src/gcc/cp/decl2.c:4512
```
which looks a lot like https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77545.
The error seems to be that it gets confused about the `std::tuple<...>
value` in argument_loader: it is apparently not being initialized
properly. Adding a default constructor with an explicit
default-initialization of `value` works around the problem.
2016-12-14 00:11:36 +00:00
|
|
|
|
2017-01-22 04:42:14 +00:00
|
|
|
public:
|
feat: allow kw-only args after a py::args (#3402)
* Simply has_kw_only_args handling
This simplifies tracking the number of kw-only args by instead tracking
the number of positional arguments (which is really what we care about
everywhere this is used).
* Allow keyword-only arguments to follow py::args
This removes the constraint that py::args has to be last (or
second-last, with py::kwargs) and instead makes py::args imply
py::kw_only for any remaining arguments, allowing you to bind a function
that works the same way as a Python function such as:
def f(a, *args, b):
return a * b + sum(args)
f(10, 1, 2, 3, b=20) # == 206
With this change, you can bind such a function using:
m.def("f", [](int a, py::args args, int b) { /* ... */ },
"a"_a, "b"_a);
Or, to be more explicit about the keyword-only arguments:
m.def("g", [](int a, py::args args, int b) { /* ... */ },
"a"_a, py::kw_only{}, "b"_a);
(The only difference between the two is that the latter will fail at
binding time if the `kw_only{}` doesn't match the `py::args` position).
This doesn't affect backwards compatibility at all because, currently,
you can't have a py::args anywhere except the end/2nd-last.
* Take args/kwargs by const lvalue ref
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
2021-10-29 03:16:55 +00:00
|
|
|
static constexpr bool has_kwargs = kwargs_pos != -1;
|
|
|
|
|
|
|
|
// py::args argument position; -1 if not present.
|
|
|
|
static constexpr int args_pos = constexpr_last<argument_is_args, Args...>();
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
static_assert(args_pos == -1 || args_pos == constexpr_first<argument_is_args, Args...>(),
|
|
|
|
"py::args cannot be specified more than once");
|
2016-11-27 17:19:34 +00:00
|
|
|
|
2024-03-27 20:51:03 +00:00
|
|
|
static constexpr auto arg_names
|
|
|
|
= ::pybind11::detail::concat(type_descr(make_caster<Args>::name)...);
|
2016-11-27 17:19:34 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
bool load_args(function_call &call) { return load_impl_sequence(call, indices{}); }
|
2016-11-27 17:19:34 +00:00
|
|
|
|
2017-03-16 10:22:26 +00:00
|
|
|
template <typename Return, typename Guard, typename Func>
|
2021-09-10 04:27:36 +00:00
|
|
|
// NOLINTNEXTLINE(readability-const-return-type)
|
2017-05-14 19:57:26 +00:00
|
|
|
enable_if_t<!std::is_void<Return>::value, Return> call(Func &&f) && {
|
2022-02-10 20:17:07 +00:00
|
|
|
return std::move(*this).template call_impl<remove_cv_t<Return>>(
|
|
|
|
std::forward<Func>(f), indices{}, Guard{});
|
2016-11-27 17:19:34 +00:00
|
|
|
}
|
|
|
|
|
2017-03-16 10:22:26 +00:00
|
|
|
template <typename Return, typename Guard, typename Func>
|
2017-05-14 19:57:26 +00:00
|
|
|
enable_if_t<std::is_void<Return>::value, void_type> call(Func &&f) && {
|
2022-02-10 20:17:07 +00:00
|
|
|
std::move(*this).template call_impl<remove_cv_t<Return>>(
|
|
|
|
std::forward<Func>(f), indices{}, Guard{});
|
2016-11-27 17:19:34 +00:00
|
|
|
return void_type();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
static bool load_impl_sequence(function_call &, index_sequence<>) { return true; }
|
2016-11-27 17:19:34 +00:00
|
|
|
|
|
|
|
template <size_t... Is>
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
bool load_impl_sequence(function_call &call, index_sequence<Is...>) {
|
2019-12-30 00:26:32 +00:00
|
|
|
#ifdef __cpp_fold_expressions
|
2022-02-08 00:17:32 +00:00
|
|
|
if ((... || !std::get<Is>(argcasters).load(call.args[Is], call.args_convert[Is]))) {
|
2019-12-30 00:26:32 +00:00
|
|
|
return false;
|
2022-02-08 00:17:32 +00:00
|
|
|
}
|
2019-12-30 00:26:32 +00:00
|
|
|
#else
|
2022-02-08 00:17:32 +00:00
|
|
|
for (bool r : {std::get<Is>(argcasters).load(call.args[Is], call.args_convert[Is])...}) {
|
|
|
|
if (!r) {
|
2016-11-27 17:19:34 +00:00
|
|
|
return false;
|
2022-02-08 00:17:32 +00:00
|
|
|
}
|
|
|
|
}
|
2019-12-30 00:26:32 +00:00
|
|
|
#endif
|
2016-11-27 17:19:34 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-03-16 10:22:26 +00:00
|
|
|
template <typename Return, typename Func, size_t... Is, typename Guard>
|
2020-01-05 14:49:24 +00:00
|
|
|
Return call_impl(Func &&f, index_sequence<Is...>, Guard &&) && {
|
2017-05-14 19:57:26 +00:00
|
|
|
return std::forward<Func>(f)(cast_op<Args>(std::move(std::get<Is>(argcasters)))...);
|
2016-11-27 17:19:34 +00:00
|
|
|
}
|
|
|
|
|
2017-05-14 19:57:26 +00:00
|
|
|
std::tuple<make_caster<Args>...> argcasters;
|
2016-11-27 17:19:34 +00:00
|
|
|
};
|
|
|
|
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
/// Helper class which collects only positional arguments for a Python function call.
|
|
|
|
/// A fancier version below can collect any argument, but this one is optimal for simple calls.
|
|
|
|
template <return_value_policy policy>
|
|
|
|
class simple_collector {
|
|
|
|
public:
|
|
|
|
template <typename... Ts>
|
2016-10-16 20:27:42 +00:00
|
|
|
explicit simple_collector(Ts &&...values)
|
2022-02-10 20:17:07 +00:00
|
|
|
: m_args(pybind11::make_tuple<policy>(std::forward<Ts>(values)...)) {}
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
|
|
|
|
const tuple &args() const & { return m_args; }
|
|
|
|
dict kwargs() const { return {}; }
|
|
|
|
|
|
|
|
tuple args() && { return std::move(m_args); }
|
|
|
|
|
|
|
|
/// Call a Python function and pass the collected arguments
|
|
|
|
object call(PyObject *ptr) const {
|
2016-10-28 01:08:15 +00:00
|
|
|
PyObject *result = PyObject_CallObject(ptr, m_args.ptr());
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!result) {
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
throw error_already_set();
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-10-28 01:08:15 +00:00
|
|
|
return reinterpret_steal<object>(result);
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
tuple m_args;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Helper class which collects positional, keyword, * and ** arguments for a Python function call
|
|
|
|
template <return_value_policy policy>
|
|
|
|
class unpacking_collector {
|
|
|
|
public:
|
|
|
|
template <typename... Ts>
|
2016-10-16 20:27:42 +00:00
|
|
|
explicit unpacking_collector(Ts &&...values) {
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
// Tuples aren't (easily) resizable so a list is needed for collection,
|
|
|
|
// but the actual function call strictly requires a tuple.
|
|
|
|
auto args_list = list();
|
2021-08-06 19:27:11 +00:00
|
|
|
using expander = int[];
|
|
|
|
(void) expander{0, (process(args_list, std::forward<Ts>(values)), 0)...};
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
|
2016-10-25 20:12:39 +00:00
|
|
|
m_args = std::move(args_list);
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const tuple &args() const & { return m_args; }
|
|
|
|
const dict &kwargs() const & { return m_kwargs; }
|
|
|
|
|
|
|
|
tuple args() && { return std::move(m_args); }
|
|
|
|
dict kwargs() && { return std::move(m_kwargs); }
|
|
|
|
|
|
|
|
/// Call a Python function and pass the collected arguments
|
|
|
|
object call(PyObject *ptr) const {
|
2016-10-28 01:08:15 +00:00
|
|
|
PyObject *result = PyObject_Call(ptr, m_args.ptr(), m_kwargs.ptr());
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!result) {
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
throw error_already_set();
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-10-28 01:08:15 +00:00
|
|
|
return reinterpret_steal<object>(result);
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
template <typename T>
|
|
|
|
void process(list &args_list, T &&x) {
|
2022-02-10 20:17:07 +00:00
|
|
|
auto o = reinterpret_steal<object>(
|
|
|
|
detail::make_caster<T>::cast(std::forward<T>(x), policy, {}));
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
if (!o) {
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
2023-02-10 05:21:17 +00:00
|
|
|
throw cast_error_unable_to_convert_call_arg(std::to_string(args_list.size()));
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
#else
|
2022-02-10 20:17:07 +00:00
|
|
|
throw cast_error_unable_to_convert_call_arg(std::to_string(args_list.size()),
|
|
|
|
type_id<T>());
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
#endif
|
|
|
|
}
|
2022-04-05 18:36:39 +00:00
|
|
|
args_list.append(std::move(o));
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void process(list &args_list, detail::args_proxy ap) {
|
2022-02-08 00:23:20 +00:00
|
|
|
for (auto a : ap) {
|
2016-09-08 15:02:04 +00:00
|
|
|
args_list.append(a);
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
void process(list & /*args_list*/, arg_v a) {
|
2022-02-08 00:17:32 +00:00
|
|
|
if (!a.name) {
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
nameless_argument_error();
|
|
|
|
#else
|
|
|
|
nameless_argument_error(a.type);
|
|
|
|
#endif
|
2022-02-08 00:17:32 +00:00
|
|
|
}
|
2016-09-20 23:06:32 +00:00
|
|
|
if (m_kwargs.contains(a.name)) {
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
multiple_values_error();
|
|
|
|
#else
|
|
|
|
multiple_values_error(a.name);
|
|
|
|
#endif
|
|
|
|
}
|
2016-09-05 22:49:21 +00:00
|
|
|
if (!a.value) {
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
2023-02-10 05:21:17 +00:00
|
|
|
throw cast_error_unable_to_convert_call_arg(a.name);
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
#else
|
2021-07-06 22:13:13 +00:00
|
|
|
throw cast_error_unable_to_convert_call_arg(a.name, a.type);
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
#endif
|
|
|
|
}
|
2022-10-06 20:11:34 +00:00
|
|
|
m_kwargs[a.name] = std::move(a.value);
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
void process(list & /*args_list*/, detail::kwargs_proxy kp) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!kp) {
|
2016-10-08 13:30:00 +00:00
|
|
|
return;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2020-09-19 18:23:47 +00:00
|
|
|
for (auto k : reinterpret_borrow<dict>(kp)) {
|
2016-09-20 23:06:32 +00:00
|
|
|
if (m_kwargs.contains(k.first)) {
|
2022-05-02 19:30:19 +00:00
|
|
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
multiple_values_error();
|
|
|
|
#else
|
2016-10-25 20:12:39 +00:00
|
|
|
multiple_values_error(str(k.first));
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
m_kwargs[k.first] = k.second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
[[noreturn]] static void nameless_argument_error() {
|
2022-05-02 19:30:19 +00:00
|
|
|
throw type_error(
|
|
|
|
"Got kwargs without a name; only named arguments "
|
|
|
|
"may be passed via py::arg() to a python function call. "
|
|
|
|
"(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)");
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
}
|
2021-06-19 17:53:27 +00:00
|
|
|
[[noreturn]] static void nameless_argument_error(const std::string &type) {
|
2022-02-10 20:17:07 +00:00
|
|
|
throw type_error("Got kwargs without a name of type '" + type
|
|
|
|
+ "'; only named "
|
|
|
|
"arguments may be passed via py::arg() to a python function call. ");
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
}
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
[[noreturn]] static void multiple_values_error() {
|
2022-05-02 19:30:19 +00:00
|
|
|
throw type_error(
|
|
|
|
"Got multiple values for keyword argument "
|
|
|
|
"(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)");
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
}
|
|
|
|
|
2021-06-19 17:53:27 +00:00
|
|
|
[[noreturn]] static void multiple_values_error(const std::string &name) {
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
throw type_error("Got multiple values for keyword argument '" + name + "'");
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
tuple m_args;
|
|
|
|
dict m_kwargs;
|
|
|
|
};
|
|
|
|
|
fix: Intel ICC C++17 compatibility (#2729)
* CI: Intel icc/icpc via oneAPI
Add testing for Intel icc/icpc via the oneAPI images.
Intel oneAPI is in a late beta stage, currently shipping
oneAPI beta09 with ICC 20.2.
CI: Skip Interpreter Tests for Intel
Cannot find how to add this, neiter the package `libc6-dev` nor
`intel-oneapi-mkl-devel` help when installed to solve this:
```
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - not found
CMake Error at /__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:165 (message):
Could NOT find Threads (missing: Threads_FOUND)
Call Stack (most recent call first):
/__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:458 (_FPHSA_FAILURE_MESSAGE)
/__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindThreads.cmake:234 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
tests/test_embed/CMakeLists.txt:17 (find_package)
```
CI: libc6-dev from GCC for ICC
CI: Run bare metal for oneAPI
CI: Ubuntu 18.04 for oneAPI
CI: Intel +Catch -Eigen
CI: CMake from Apt (ICC tests)
CI: Replace Intel Py with GCC Py
CI: Intel w/o GCC's Eigen
CI: ICC with verbose make
[Debug] Find core dump
tests: use arg{} instead of arg() for Intel
tests: adding a few more missing {}
fix: sync with @tobiasleibner's branch
fix: try ubuntu 20-04
fix: drop exit 1
docs: Apply suggestions from code review
Co-authored-by: Tobias Leibner <tobias.leibner@googlemail.com>
Workaround for ICC enable_if issues
Another workaround for ICC's enable_if issues
fix error in previous commit
Disable one test for the Intel compiler in C++17 mode
Add back one instance of py::arg().noconvert()
Add NOLINT to fix clang-tidy check
Work around for ICC internal error in PYBIND11_EXPAND_SIDE_EFFECTS in C++17 mode
CI: Intel ICC with C++17
docs: pybind11/numpy.h does not require numpy at build time. (#2720)
This is nice enough to be mentioned explicitly in the docs.
docs: Update warning about Python 3.9.0 UB, now that 3.9.1 has been released (#2719)
Adjusting `type_caster<std::reference_wrapper<T>>` to support const/non-const propagation in `cast_op`. (#2705)
* Allow type_caster of std::reference_wrapper<T> to be the same as a native reference.
Before, both std::reference_wrapper<T> and std::reference_wrapper<const T> would
invoke cast_op<type>. This doesn't allow the type_caster<> specialization for T
to distinguish reference_wrapper types from value types.
After, the type_caster<> specialization invokes cast_op<type&>, which allows
reference_wrapper to behave in the same way as a native reference type.
* Add tests/examples for std::reference_wrapper<const T>
* Add tests which use mutable/immutable variants
This test is a chimera; it blends the pybind11 casters with a custom
pytype implementation that supports immutable and mutable calls.
In order to detect the immutable/mutable state, the cast_op needs
to propagate it, even through e.g. std::reference<const T>
Note: This is still a work in progress; some things are crashing,
which likely means that I have a refcounting bug or something else
missing.
* Add/finish tests that distinguish const& from &
Fixes the bugs in my custom python type implementation,
demonstrate test that requires const& and reference_wrapper<const T>
being treated differently from Non-const.
* Add passing a const to non-const method.
* Demonstrate non-const conversion of reference_wrapper in tests.
Apply formatting presubmit check.
* Fix build errors from presubmit checks.
* Try and fix a few more CI errors
* More CI fixes.
* More CI fixups.
* Try and get PyPy to work.
* Additional minor fixups. Getting close to CI green.
* More ci fixes?
* fix clang-tidy warnings from presubmit
* fix more clang-tidy warnings
* minor comment and consistency cleanups
* PyDECREF -> Py_DECREF
* copy/move constructors
* Resolve codereview comments
* more review comment fixes
* review comments: remove spurious &
* Make the test fail even when the static_assert is commented out.
This expands the test_freezable_type_caster a bit by:
1/ adding accessors .is_immutable and .addr to compare identity
from python.
2/ Changing the default cast_op of the type_caster<> specialization
to return a non-const value. In normal codepaths this is a reasonable
default.
3/ adding roundtrip variants to exercise the by reference, by pointer
and by reference_wrapper in all call paths. In conjunction with 2/, this
demonstrates the failure case of the existing std::reference_wrpper conversion,
which now loses const in a similar way that happens when using the default cast_op_type<>.
* apply presubmit formatting
* Revert inclusion of test_freezable_type_caster
There's some concern that this test is a bit unwieldly because of the use
of the raw <Python.h> functions. Removing for now.
* Add a test that validates const references propagation.
This test verifies that cast_op may be used to correctly detect
const reference types when used with std::reference_wrapper.
* mend
* Review comments based changes.
1. std::add_lvalue_reference<type> -> type&
2. Simplify the test a little more; we're never returning the ConstRefCaster
type so the class_ definition can be removed.
* formatted files again.
* Move const_ref_caster test to builtin_casters
* Review comments: use cast_op and adjust some comments.
* Simplify ConstRefCasted test
I like this version better as it moves the assertion that matters
back into python.
ci: drop pypy2 linux, PGI 20.7, add Python 10 dev (#2724)
* ci: drop pypy2 linux, add Python 10 dev
* ci: fix mistake
* ci: commented-out PGI 20.11, drop 20.7
fix: regression with installed pybind11 overriding local one (#2716)
* fix: regression with installed pybind11 overriding discovered one
Closes #2709
* docs: wording incorrect
style: remove redundant instance->owned = true (#2723)
which was just before set to True in instance->allocate_layout()
fix: also throw in the move-constructor added by the PYBIND11_OBJECT macro, after the argument has been moved-out (if necessary) (#2701)
Make args_are_all_* ICC workarounds unconditional
Disable test_aligned on Intel ICC
Fix test_aligned on Intel ICC
Skip test_python_alreadyset_in_destructor on Intel ICC
Fix test_aligned again
ICC CI: Downgrade pytest
pytest 6 does not capture the `discard_as_unraisable` stderr and
just writes a warning with its content instead.
* refactor: simpler Intel workaround, suggested by @laramiel
* fix: try version with impl to see if it is easier to compile
* docs: update README for ICC
Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
2021-01-18 00:53:07 +00:00
|
|
|
// [workaround(intel)] Separate function required here
|
|
|
|
// We need to put this into a separate function because the Intel compiler
|
|
|
|
// fails to compile enable_if_t<!all_of<is_positional<Args>...>::value>
|
|
|
|
// (tested with ICC 2021.1 Beta 20200827).
|
|
|
|
template <typename... Args>
|
2022-02-10 20:17:07 +00:00
|
|
|
constexpr bool args_are_all_positional() {
|
|
|
|
return all_of<is_positional<Args>...>::value;
|
fix: Intel ICC C++17 compatibility (#2729)
* CI: Intel icc/icpc via oneAPI
Add testing for Intel icc/icpc via the oneAPI images.
Intel oneAPI is in a late beta stage, currently shipping
oneAPI beta09 with ICC 20.2.
CI: Skip Interpreter Tests for Intel
Cannot find how to add this, neiter the package `libc6-dev` nor
`intel-oneapi-mkl-devel` help when installed to solve this:
```
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - not found
CMake Error at /__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:165 (message):
Could NOT find Threads (missing: Threads_FOUND)
Call Stack (most recent call first):
/__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:458 (_FPHSA_FAILURE_MESSAGE)
/__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindThreads.cmake:234 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
tests/test_embed/CMakeLists.txt:17 (find_package)
```
CI: libc6-dev from GCC for ICC
CI: Run bare metal for oneAPI
CI: Ubuntu 18.04 for oneAPI
CI: Intel +Catch -Eigen
CI: CMake from Apt (ICC tests)
CI: Replace Intel Py with GCC Py
CI: Intel w/o GCC's Eigen
CI: ICC with verbose make
[Debug] Find core dump
tests: use arg{} instead of arg() for Intel
tests: adding a few more missing {}
fix: sync with @tobiasleibner's branch
fix: try ubuntu 20-04
fix: drop exit 1
docs: Apply suggestions from code review
Co-authored-by: Tobias Leibner <tobias.leibner@googlemail.com>
Workaround for ICC enable_if issues
Another workaround for ICC's enable_if issues
fix error in previous commit
Disable one test for the Intel compiler in C++17 mode
Add back one instance of py::arg().noconvert()
Add NOLINT to fix clang-tidy check
Work around for ICC internal error in PYBIND11_EXPAND_SIDE_EFFECTS in C++17 mode
CI: Intel ICC with C++17
docs: pybind11/numpy.h does not require numpy at build time. (#2720)
This is nice enough to be mentioned explicitly in the docs.
docs: Update warning about Python 3.9.0 UB, now that 3.9.1 has been released (#2719)
Adjusting `type_caster<std::reference_wrapper<T>>` to support const/non-const propagation in `cast_op`. (#2705)
* Allow type_caster of std::reference_wrapper<T> to be the same as a native reference.
Before, both std::reference_wrapper<T> and std::reference_wrapper<const T> would
invoke cast_op<type>. This doesn't allow the type_caster<> specialization for T
to distinguish reference_wrapper types from value types.
After, the type_caster<> specialization invokes cast_op<type&>, which allows
reference_wrapper to behave in the same way as a native reference type.
* Add tests/examples for std::reference_wrapper<const T>
* Add tests which use mutable/immutable variants
This test is a chimera; it blends the pybind11 casters with a custom
pytype implementation that supports immutable and mutable calls.
In order to detect the immutable/mutable state, the cast_op needs
to propagate it, even through e.g. std::reference<const T>
Note: This is still a work in progress; some things are crashing,
which likely means that I have a refcounting bug or something else
missing.
* Add/finish tests that distinguish const& from &
Fixes the bugs in my custom python type implementation,
demonstrate test that requires const& and reference_wrapper<const T>
being treated differently from Non-const.
* Add passing a const to non-const method.
* Demonstrate non-const conversion of reference_wrapper in tests.
Apply formatting presubmit check.
* Fix build errors from presubmit checks.
* Try and fix a few more CI errors
* More CI fixes.
* More CI fixups.
* Try and get PyPy to work.
* Additional minor fixups. Getting close to CI green.
* More ci fixes?
* fix clang-tidy warnings from presubmit
* fix more clang-tidy warnings
* minor comment and consistency cleanups
* PyDECREF -> Py_DECREF
* copy/move constructors
* Resolve codereview comments
* more review comment fixes
* review comments: remove spurious &
* Make the test fail even when the static_assert is commented out.
This expands the test_freezable_type_caster a bit by:
1/ adding accessors .is_immutable and .addr to compare identity
from python.
2/ Changing the default cast_op of the type_caster<> specialization
to return a non-const value. In normal codepaths this is a reasonable
default.
3/ adding roundtrip variants to exercise the by reference, by pointer
and by reference_wrapper in all call paths. In conjunction with 2/, this
demonstrates the failure case of the existing std::reference_wrpper conversion,
which now loses const in a similar way that happens when using the default cast_op_type<>.
* apply presubmit formatting
* Revert inclusion of test_freezable_type_caster
There's some concern that this test is a bit unwieldly because of the use
of the raw <Python.h> functions. Removing for now.
* Add a test that validates const references propagation.
This test verifies that cast_op may be used to correctly detect
const reference types when used with std::reference_wrapper.
* mend
* Review comments based changes.
1. std::add_lvalue_reference<type> -> type&
2. Simplify the test a little more; we're never returning the ConstRefCaster
type so the class_ definition can be removed.
* formatted files again.
* Move const_ref_caster test to builtin_casters
* Review comments: use cast_op and adjust some comments.
* Simplify ConstRefCasted test
I like this version better as it moves the assertion that matters
back into python.
ci: drop pypy2 linux, PGI 20.7, add Python 10 dev (#2724)
* ci: drop pypy2 linux, add Python 10 dev
* ci: fix mistake
* ci: commented-out PGI 20.11, drop 20.7
fix: regression with installed pybind11 overriding local one (#2716)
* fix: regression with installed pybind11 overriding discovered one
Closes #2709
* docs: wording incorrect
style: remove redundant instance->owned = true (#2723)
which was just before set to True in instance->allocate_layout()
fix: also throw in the move-constructor added by the PYBIND11_OBJECT macro, after the argument has been moved-out (if necessary) (#2701)
Make args_are_all_* ICC workarounds unconditional
Disable test_aligned on Intel ICC
Fix test_aligned on Intel ICC
Skip test_python_alreadyset_in_destructor on Intel ICC
Fix test_aligned again
ICC CI: Downgrade pytest
pytest 6 does not capture the `discard_as_unraisable` stderr and
just writes a warning with its content instead.
* refactor: simpler Intel workaround, suggested by @laramiel
* fix: try version with impl to see if it is easier to compile
* docs: update README for ICC
Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
2021-01-18 00:53:07 +00:00
|
|
|
}
|
|
|
|
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
/// Collect only positional arguments for a Python function call
|
2022-02-10 20:17:07 +00:00
|
|
|
template <return_value_policy policy,
|
|
|
|
typename... Args,
|
fix: Intel ICC C++17 compatibility (#2729)
* CI: Intel icc/icpc via oneAPI
Add testing for Intel icc/icpc via the oneAPI images.
Intel oneAPI is in a late beta stage, currently shipping
oneAPI beta09 with ICC 20.2.
CI: Skip Interpreter Tests for Intel
Cannot find how to add this, neiter the package `libc6-dev` nor
`intel-oneapi-mkl-devel` help when installed to solve this:
```
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - not found
CMake Error at /__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:165 (message):
Could NOT find Threads (missing: Threads_FOUND)
Call Stack (most recent call first):
/__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:458 (_FPHSA_FAILURE_MESSAGE)
/__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindThreads.cmake:234 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
tests/test_embed/CMakeLists.txt:17 (find_package)
```
CI: libc6-dev from GCC for ICC
CI: Run bare metal for oneAPI
CI: Ubuntu 18.04 for oneAPI
CI: Intel +Catch -Eigen
CI: CMake from Apt (ICC tests)
CI: Replace Intel Py with GCC Py
CI: Intel w/o GCC's Eigen
CI: ICC with verbose make
[Debug] Find core dump
tests: use arg{} instead of arg() for Intel
tests: adding a few more missing {}
fix: sync with @tobiasleibner's branch
fix: try ubuntu 20-04
fix: drop exit 1
docs: Apply suggestions from code review
Co-authored-by: Tobias Leibner <tobias.leibner@googlemail.com>
Workaround for ICC enable_if issues
Another workaround for ICC's enable_if issues
fix error in previous commit
Disable one test for the Intel compiler in C++17 mode
Add back one instance of py::arg().noconvert()
Add NOLINT to fix clang-tidy check
Work around for ICC internal error in PYBIND11_EXPAND_SIDE_EFFECTS in C++17 mode
CI: Intel ICC with C++17
docs: pybind11/numpy.h does not require numpy at build time. (#2720)
This is nice enough to be mentioned explicitly in the docs.
docs: Update warning about Python 3.9.0 UB, now that 3.9.1 has been released (#2719)
Adjusting `type_caster<std::reference_wrapper<T>>` to support const/non-const propagation in `cast_op`. (#2705)
* Allow type_caster of std::reference_wrapper<T> to be the same as a native reference.
Before, both std::reference_wrapper<T> and std::reference_wrapper<const T> would
invoke cast_op<type>. This doesn't allow the type_caster<> specialization for T
to distinguish reference_wrapper types from value types.
After, the type_caster<> specialization invokes cast_op<type&>, which allows
reference_wrapper to behave in the same way as a native reference type.
* Add tests/examples for std::reference_wrapper<const T>
* Add tests which use mutable/immutable variants
This test is a chimera; it blends the pybind11 casters with a custom
pytype implementation that supports immutable and mutable calls.
In order to detect the immutable/mutable state, the cast_op needs
to propagate it, even through e.g. std::reference<const T>
Note: This is still a work in progress; some things are crashing,
which likely means that I have a refcounting bug or something else
missing.
* Add/finish tests that distinguish const& from &
Fixes the bugs in my custom python type implementation,
demonstrate test that requires const& and reference_wrapper<const T>
being treated differently from Non-const.
* Add passing a const to non-const method.
* Demonstrate non-const conversion of reference_wrapper in tests.
Apply formatting presubmit check.
* Fix build errors from presubmit checks.
* Try and fix a few more CI errors
* More CI fixes.
* More CI fixups.
* Try and get PyPy to work.
* Additional minor fixups. Getting close to CI green.
* More ci fixes?
* fix clang-tidy warnings from presubmit
* fix more clang-tidy warnings
* minor comment and consistency cleanups
* PyDECREF -> Py_DECREF
* copy/move constructors
* Resolve codereview comments
* more review comment fixes
* review comments: remove spurious &
* Make the test fail even when the static_assert is commented out.
This expands the test_freezable_type_caster a bit by:
1/ adding accessors .is_immutable and .addr to compare identity
from python.
2/ Changing the default cast_op of the type_caster<> specialization
to return a non-const value. In normal codepaths this is a reasonable
default.
3/ adding roundtrip variants to exercise the by reference, by pointer
and by reference_wrapper in all call paths. In conjunction with 2/, this
demonstrates the failure case of the existing std::reference_wrpper conversion,
which now loses const in a similar way that happens when using the default cast_op_type<>.
* apply presubmit formatting
* Revert inclusion of test_freezable_type_caster
There's some concern that this test is a bit unwieldly because of the use
of the raw <Python.h> functions. Removing for now.
* Add a test that validates const references propagation.
This test verifies that cast_op may be used to correctly detect
const reference types when used with std::reference_wrapper.
* mend
* Review comments based changes.
1. std::add_lvalue_reference<type> -> type&
2. Simplify the test a little more; we're never returning the ConstRefCaster
type so the class_ definition can be removed.
* formatted files again.
* Move const_ref_caster test to builtin_casters
* Review comments: use cast_op and adjust some comments.
* Simplify ConstRefCasted test
I like this version better as it moves the assertion that matters
back into python.
ci: drop pypy2 linux, PGI 20.7, add Python 10 dev (#2724)
* ci: drop pypy2 linux, add Python 10 dev
* ci: fix mistake
* ci: commented-out PGI 20.11, drop 20.7
fix: regression with installed pybind11 overriding local one (#2716)
* fix: regression with installed pybind11 overriding discovered one
Closes #2709
* docs: wording incorrect
style: remove redundant instance->owned = true (#2723)
which was just before set to True in instance->allocate_layout()
fix: also throw in the move-constructor added by the PYBIND11_OBJECT macro, after the argument has been moved-out (if necessary) (#2701)
Make args_are_all_* ICC workarounds unconditional
Disable test_aligned on Intel ICC
Fix test_aligned on Intel ICC
Skip test_python_alreadyset_in_destructor on Intel ICC
Fix test_aligned again
ICC CI: Downgrade pytest
pytest 6 does not capture the `discard_as_unraisable` stderr and
just writes a warning with its content instead.
* refactor: simpler Intel workaround, suggested by @laramiel
* fix: try version with impl to see if it is easier to compile
* docs: update README for ICC
Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
2021-01-18 00:53:07 +00:00
|
|
|
typename = enable_if_t<args_are_all_positional<Args...>()>>
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
simple_collector<policy> collect_arguments(Args &&...args) {
|
2016-10-16 20:27:42 +00:00
|
|
|
return simple_collector<policy>(std::forward<Args>(args)...);
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Collect all arguments, including keywords and unpacking (only instantiated when needed)
|
2022-02-10 20:17:07 +00:00
|
|
|
template <return_value_policy policy,
|
|
|
|
typename... Args,
|
fix: Intel ICC C++17 compatibility (#2729)
* CI: Intel icc/icpc via oneAPI
Add testing for Intel icc/icpc via the oneAPI images.
Intel oneAPI is in a late beta stage, currently shipping
oneAPI beta09 with ICC 20.2.
CI: Skip Interpreter Tests for Intel
Cannot find how to add this, neiter the package `libc6-dev` nor
`intel-oneapi-mkl-devel` help when installed to solve this:
```
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - not found
CMake Error at /__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:165 (message):
Could NOT find Threads (missing: Threads_FOUND)
Call Stack (most recent call first):
/__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:458 (_FPHSA_FAILURE_MESSAGE)
/__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindThreads.cmake:234 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
tests/test_embed/CMakeLists.txt:17 (find_package)
```
CI: libc6-dev from GCC for ICC
CI: Run bare metal for oneAPI
CI: Ubuntu 18.04 for oneAPI
CI: Intel +Catch -Eigen
CI: CMake from Apt (ICC tests)
CI: Replace Intel Py with GCC Py
CI: Intel w/o GCC's Eigen
CI: ICC with verbose make
[Debug] Find core dump
tests: use arg{} instead of arg() for Intel
tests: adding a few more missing {}
fix: sync with @tobiasleibner's branch
fix: try ubuntu 20-04
fix: drop exit 1
docs: Apply suggestions from code review
Co-authored-by: Tobias Leibner <tobias.leibner@googlemail.com>
Workaround for ICC enable_if issues
Another workaround for ICC's enable_if issues
fix error in previous commit
Disable one test for the Intel compiler in C++17 mode
Add back one instance of py::arg().noconvert()
Add NOLINT to fix clang-tidy check
Work around for ICC internal error in PYBIND11_EXPAND_SIDE_EFFECTS in C++17 mode
CI: Intel ICC with C++17
docs: pybind11/numpy.h does not require numpy at build time. (#2720)
This is nice enough to be mentioned explicitly in the docs.
docs: Update warning about Python 3.9.0 UB, now that 3.9.1 has been released (#2719)
Adjusting `type_caster<std::reference_wrapper<T>>` to support const/non-const propagation in `cast_op`. (#2705)
* Allow type_caster of std::reference_wrapper<T> to be the same as a native reference.
Before, both std::reference_wrapper<T> and std::reference_wrapper<const T> would
invoke cast_op<type>. This doesn't allow the type_caster<> specialization for T
to distinguish reference_wrapper types from value types.
After, the type_caster<> specialization invokes cast_op<type&>, which allows
reference_wrapper to behave in the same way as a native reference type.
* Add tests/examples for std::reference_wrapper<const T>
* Add tests which use mutable/immutable variants
This test is a chimera; it blends the pybind11 casters with a custom
pytype implementation that supports immutable and mutable calls.
In order to detect the immutable/mutable state, the cast_op needs
to propagate it, even through e.g. std::reference<const T>
Note: This is still a work in progress; some things are crashing,
which likely means that I have a refcounting bug or something else
missing.
* Add/finish tests that distinguish const& from &
Fixes the bugs in my custom python type implementation,
demonstrate test that requires const& and reference_wrapper<const T>
being treated differently from Non-const.
* Add passing a const to non-const method.
* Demonstrate non-const conversion of reference_wrapper in tests.
Apply formatting presubmit check.
* Fix build errors from presubmit checks.
* Try and fix a few more CI errors
* More CI fixes.
* More CI fixups.
* Try and get PyPy to work.
* Additional minor fixups. Getting close to CI green.
* More ci fixes?
* fix clang-tidy warnings from presubmit
* fix more clang-tidy warnings
* minor comment and consistency cleanups
* PyDECREF -> Py_DECREF
* copy/move constructors
* Resolve codereview comments
* more review comment fixes
* review comments: remove spurious &
* Make the test fail even when the static_assert is commented out.
This expands the test_freezable_type_caster a bit by:
1/ adding accessors .is_immutable and .addr to compare identity
from python.
2/ Changing the default cast_op of the type_caster<> specialization
to return a non-const value. In normal codepaths this is a reasonable
default.
3/ adding roundtrip variants to exercise the by reference, by pointer
and by reference_wrapper in all call paths. In conjunction with 2/, this
demonstrates the failure case of the existing std::reference_wrpper conversion,
which now loses const in a similar way that happens when using the default cast_op_type<>.
* apply presubmit formatting
* Revert inclusion of test_freezable_type_caster
There's some concern that this test is a bit unwieldly because of the use
of the raw <Python.h> functions. Removing for now.
* Add a test that validates const references propagation.
This test verifies that cast_op may be used to correctly detect
const reference types when used with std::reference_wrapper.
* mend
* Review comments based changes.
1. std::add_lvalue_reference<type> -> type&
2. Simplify the test a little more; we're never returning the ConstRefCaster
type so the class_ definition can be removed.
* formatted files again.
* Move const_ref_caster test to builtin_casters
* Review comments: use cast_op and adjust some comments.
* Simplify ConstRefCasted test
I like this version better as it moves the assertion that matters
back into python.
ci: drop pypy2 linux, PGI 20.7, add Python 10 dev (#2724)
* ci: drop pypy2 linux, add Python 10 dev
* ci: fix mistake
* ci: commented-out PGI 20.11, drop 20.7
fix: regression with installed pybind11 overriding local one (#2716)
* fix: regression with installed pybind11 overriding discovered one
Closes #2709
* docs: wording incorrect
style: remove redundant instance->owned = true (#2723)
which was just before set to True in instance->allocate_layout()
fix: also throw in the move-constructor added by the PYBIND11_OBJECT macro, after the argument has been moved-out (if necessary) (#2701)
Make args_are_all_* ICC workarounds unconditional
Disable test_aligned on Intel ICC
Fix test_aligned on Intel ICC
Skip test_python_alreadyset_in_destructor on Intel ICC
Fix test_aligned again
ICC CI: Downgrade pytest
pytest 6 does not capture the `discard_as_unraisable` stderr and
just writes a warning with its content instead.
* refactor: simpler Intel workaround, suggested by @laramiel
* fix: try version with impl to see if it is easier to compile
* docs: update README for ICC
Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
2021-01-18 00:53:07 +00:00
|
|
|
typename = enable_if_t<!args_are_all_positional<Args...>()>>
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
unpacking_collector<policy> collect_arguments(Args &&...args) {
|
|
|
|
// Following argument order rules for generalized unpacking according to PEP 448
|
2022-02-10 20:17:07 +00:00
|
|
|
static_assert(constexpr_last<is_positional, Args...>()
|
|
|
|
< constexpr_first<is_keyword_or_ds, Args...>()
|
|
|
|
&& constexpr_last<is_s_unpacking, Args...>()
|
|
|
|
< constexpr_first<is_ds_unpacking, Args...>(),
|
|
|
|
"Invalid function call: positional args must precede keywords and ** unpacking; "
|
|
|
|
"* unpacking must precede ** unpacking");
|
2016-10-16 20:27:42 +00:00
|
|
|
return unpacking_collector<policy>(std::forward<Args>(args)...);
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
}
|
|
|
|
|
2016-09-08 14:36:01 +00:00
|
|
|
template <typename Derived>
|
Support keyword arguments and generalized unpacking in C++
A Python function can be called with the syntax:
```python
foo(a1, a2, *args, ka=1, kb=2, **kwargs)
```
This commit adds support for the equivalent syntax in C++:
```c++
foo(a1, a2, *args, "ka"_a=1, "kb"_a=2, **kwargs)
```
In addition, generalized unpacking is implemented, as per PEP 448,
which allows calls with multiple * and ** unpacking:
```python
bar(*args1, 99, *args2, 101, **kwargs1, kz=200, **kwargs2)
```
and
```c++
bar(*args1, 99, *args2, 101, **kwargs1, "kz"_a=200, **kwargs2)
```
2016-08-29 01:05:42 +00:00
|
|
|
template <return_value_policy policy, typename... Args>
|
2016-09-08 14:36:01 +00:00
|
|
|
object object_api<Derived>::operator()(Args &&...args) const {
|
2022-07-12 19:02:20 +00:00
|
|
|
#ifndef NDEBUG
|
2021-04-03 01:17:12 +00:00
|
|
|
if (!PyGILState_Check()) {
|
|
|
|
pybind11_fail("pybind11::object_api<>::operator() PyGILState_Check() failure.");
|
|
|
|
}
|
|
|
|
#endif
|
2016-09-08 14:36:01 +00:00
|
|
|
return detail::collect_arguments<policy>(std::forward<Args>(args)...).call(derived().ptr());
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2016-09-08 14:36:01 +00:00
|
|
|
template <typename Derived>
|
|
|
|
template <return_value_policy policy, typename... Args>
|
|
|
|
object object_api<Derived>::call(Args &&...args) const {
|
2016-06-22 12:29:13 +00:00
|
|
|
return operator()<policy>(std::forward<Args>(args)...);
|
2016-05-08 12:34:09 +00:00
|
|
|
}
|
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_END(detail)
|
2016-09-08 14:36:01 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
2020-09-16 15:32:17 +00:00
|
|
|
handle type::handle_of() {
|
2024-07-31 13:17:31 +00:00
|
|
|
static_assert(std::is_base_of<detail::type_caster_generic, detail::make_caster<T>>::value,
|
|
|
|
"py::type::of<T> only supports the case where T is a registered C++ types.");
|
2020-09-14 22:06:26 +00:00
|
|
|
|
2020-09-16 15:32:17 +00:00
|
|
|
return detail::get_type_handle(typeid(T), true);
|
2020-09-14 22:06:26 +00:00
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
#define PYBIND11_MAKE_OPAQUE(...) \
|
2022-07-06 21:29:20 +00:00
|
|
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) \
|
2022-02-10 20:17:07 +00:00
|
|
|
namespace detail { \
|
|
|
|
template <> \
|
2024-07-31 13:17:31 +00:00
|
|
|
class type_caster<__VA_ARGS__> : public type_caster_base<__VA_ARGS__> {}; \
|
2022-02-10 20:17:07 +00:00
|
|
|
} \
|
2022-07-06 21:29:20 +00:00
|
|
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
2016-04-28 14:25:24 +00:00
|
|
|
|
2018-02-28 02:33:41 +00:00
|
|
|
/// Lets you pass a type containing a `,` through a macro parameter without needing a separate
|
2022-02-10 19:42:03 +00:00
|
|
|
/// typedef, e.g.:
|
|
|
|
/// `PYBIND11_OVERRIDE(PYBIND11_TYPE(ReturnType<A, B>), PYBIND11_TYPE(Parent<C, D>), f, arg)`
|
2018-02-28 02:33:41 +00:00
|
|
|
#define PYBIND11_TYPE(...) __VA_ARGS__
|
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|