2020-07-23 14:58:19 +08:00
/*
pybind11 / pybind11 . h : Main header file of the C + + 11 python
binding generator library
Copyright ( c ) 2016 Wenzel Jakob < wenzel . jakob @ epfl . ch >
All rights reserved . Use of this source code is governed by a
BSD - style license that can be found in the LICENSE file .
*/
# pragma once
# if defined(__INTEL_COMPILER)
# pragma warning push
# pragma warning disable 68 // integer conversion resulted in a change of sign
# pragma warning disable 186 // pointless comparison of unsigned integer with zero
# pragma warning disable 878 // incompatible exception specifications
# pragma warning disable 1334 // the "template" keyword used for syntactic disambiguation may only be used within a template
# pragma warning disable 1682 // implicit conversion of a 64-bit integral type to a smaller integral type (potential portability problem)
# pragma warning disable 1786 // function "strdup" was declared deprecated
# pragma warning disable 1875 // offsetof applied to non-POD (Plain Old Data) types is nonstandard
# pragma warning disable 2196 // warning #2196: routine is both "inline" and "noinline"
# elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
# pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted
# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
# pragma warning(disable: 4702) // warning C4702: unreachable code
# pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified
2021-01-02 17:15:39 +08:00
# pragma warning(disable: 4505) // warning C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only)
2020-07-23 14:58:19 +08:00
# elif defined(__GNUG__) && !defined(__clang__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
# pragma GCC diagnostic ignored "-Wunused-but-set-variable"
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
# pragma GCC diagnostic ignored "-Wattributes"
# if __GNUC__ >= 7
# pragma GCC diagnostic ignored "-Wnoexcept-type"
# endif
# endif
# include "attr.h"
# include "options.h"
# include "detail/class.h"
# include "detail/init.h"
2021-01-02 17:15:39 +08:00
# include <memory>
# include <vector>
# include <string>
# include <utility>
2020-07-23 14:58:19 +08:00
# if defined(__GNUG__) && !defined(__clang__)
# include <cxxabi.h>
# endif
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_BEGIN ( PYBIND11_NAMESPACE )
2020-07-23 14:58:19 +08:00
/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
class cpp_function : public function {
public :
2021-01-02 17:15:39 +08:00
cpp_function ( ) = default ;
2020-07-23 14:58:19 +08:00
cpp_function ( std : : nullptr_t ) { }
/// Construct a cpp_function from a vanilla function pointer
template < typename Return , typename . . . Args , typename . . . Extra >
cpp_function ( Return ( * f ) ( Args . . . ) , const Extra & . . . extra ) {
initialize ( f , f , extra . . . ) ;
}
/// Construct a cpp_function from a lambda function (possibly with internal state)
template < typename Func , typename . . . Extra ,
typename = detail : : enable_if_t < detail : : is_lambda < Func > : : value > >
cpp_function ( Func & & f , const Extra & . . . extra ) {
initialize ( std : : forward < Func > ( f ) ,
( detail : : function_signature_t < Func > * ) nullptr , extra . . . ) ;
}
2021-01-02 17:15:39 +08:00
/// Construct a cpp_function from a class method (non-const, no ref-qualifier)
2020-07-23 14:58:19 +08:00
template < typename Return , typename Class , typename . . . Arg , typename . . . Extra >
cpp_function ( Return ( Class : : * f ) ( Arg . . . ) , const Extra & . . . extra ) {
2021-01-02 17:15:39 +08:00
initialize ( [ f ] ( Class * c , Arg . . . args ) - > Return { return ( c - > * f ) ( std : : forward < Arg > ( args ) . . . ) ; } ,
( Return ( * ) ( Class * , Arg . . . ) ) nullptr , extra . . . ) ;
}
/// Construct a cpp_function from a class method (non-const, lvalue ref-qualifier)
/// A copy of the overload for non-const functions without explicit ref-qualifier
/// but with an added `&`.
template < typename Return , typename Class , typename . . . Arg , typename . . . Extra >
cpp_function ( Return ( Class : : * f ) ( Arg . . . ) & , const Extra & . . . extra ) {
2020-07-23 14:58:19 +08:00
initialize ( [ f ] ( Class * c , Arg . . . args ) - > Return { return ( c - > * f ) ( args . . . ) ; } ,
( Return ( * ) ( Class * , Arg . . . ) ) nullptr , extra . . . ) ;
}
2021-01-02 17:15:39 +08:00
/// Construct a cpp_function from a class method (const, no ref-qualifier)
2020-07-23 14:58:19 +08:00
template < typename Return , typename Class , typename . . . Arg , typename . . . Extra >
cpp_function ( Return ( Class : : * f ) ( Arg . . . ) const , const Extra & . . . extra ) {
2021-01-02 17:15:39 +08:00
initialize ( [ f ] ( const Class * c , Arg . . . args ) - > Return { return ( c - > * f ) ( std : : forward < Arg > ( args ) . . . ) ; } ,
( Return ( * ) ( const Class * , Arg . . . ) ) nullptr , extra . . . ) ;
}
/// Construct a cpp_function from a class method (const, lvalue ref-qualifier)
/// A copy of the overload for const functions without explicit ref-qualifier
/// but with an added `&`.
template < typename Return , typename Class , typename . . . Arg , typename . . . Extra >
cpp_function ( Return ( Class : : * f ) ( Arg . . . ) const & , const Extra & . . . extra ) {
2020-07-23 14:58:19 +08:00
initialize ( [ f ] ( const Class * c , Arg . . . args ) - > Return { return ( c - > * f ) ( args . . . ) ; } ,
( Return ( * ) ( const Class * , Arg . . . ) ) nullptr , extra . . . ) ;
}
/// Return the function name
object name ( ) const { return attr ( " __name__ " ) ; }
protected :
/// Space optimization: don't inline this frequently instantiated fragment
PYBIND11_NOINLINE detail : : function_record * make_function_record ( ) {
return new detail : : function_record ( ) ;
}
/// Special internal constructor for functors, lambda functions, etc.
template < typename Func , typename Return , typename . . . Args , typename . . . Extra >
void initialize ( Func & & f , Return ( * ) ( Args . . . ) , const Extra & . . . extra ) {
using namespace detail ;
struct capture { remove_reference_t < Func > f ; } ;
/* Store the function including any extra state it might have (e.g. a lambda capture object) */
auto rec = make_function_record ( ) ;
/* Store the capture object directly in the function record if there is enough space */
if ( sizeof ( capture ) < = sizeof ( rec - > data ) ) {
/* Without these pragmas, GCC warns that there might not be
enough space to use the placement new operator . However , the
' if ' statement above ensures that this is the case . */
# if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wplacement-new"
# endif
new ( ( capture * ) & rec - > data ) capture { std : : forward < Func > ( f ) } ;
# if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6
# pragma GCC diagnostic pop
# endif
if ( ! std : : is_trivially_destructible < Func > : : value )
rec - > free_data = [ ] ( function_record * r ) { ( ( capture * ) & r - > data ) - > ~ capture ( ) ; } ;
} else {
rec - > data [ 0 ] = new capture { std : : forward < Func > ( f ) } ;
rec - > free_data = [ ] ( function_record * r ) { delete ( ( capture * ) r - > data [ 0 ] ) ; } ;
}
/* Type casters for the function arguments and return value */
using cast_in = argument_loader < Args . . . > ;
using cast_out = make_caster <
conditional_t < std : : is_void < Return > : : value , void_type , Return >
> ;
static_assert ( expected_num_args < Extra . . . > ( sizeof . . . ( Args ) , cast_in : : has_args , cast_in : : has_kwargs ) ,
" The number of argument annotations does not match the number of function arguments " ) ;
/* Dispatch code which converts function arguments and performs the actual function call */
rec - > impl = [ ] ( function_call & call ) - > handle {
cast_in args_converter ;
/* Try to cast the function arguments into the C++ domain */
if ( ! args_converter . load_args ( call ) )
return PYBIND11_TRY_NEXT_OVERLOAD ;
/* Invoke call policy pre-call hook */
process_attributes < Extra . . . > : : precall ( call ) ;
/* Get a pointer to the capture object */
auto data = ( sizeof ( capture ) < = sizeof ( call . func . data )
? & call . func . data : call . func . data [ 0 ] ) ;
2021-01-02 17:15:39 +08:00
auto * cap = const_cast < capture * > ( reinterpret_cast < const capture * > ( data ) ) ;
2020-07-23 14:58:19 +08:00
/* Override policy for rvalues -- usually to enforce rvp::move on an rvalue */
return_value_policy policy = return_value_policy_override < Return > : : policy ( call . func . policy ) ;
/* Function scope guard -- defaults to the compile-to-nothing `void_type` */
using Guard = extract_guard_t < Extra . . . > ;
/* Perform the function call */
handle result = cast_out : : cast (
std : : move ( args_converter ) . template call < Return , Guard > ( cap - > f ) , policy , call . parent ) ;
/* Invoke call policy post-call hook */
process_attributes < Extra . . . > : : postcall ( call , result ) ;
return result ;
} ;
/* Process any user-provided function attributes */
process_attributes < Extra . . . > : : init ( extra . . . , rec ) ;
2021-01-02 17:15:39 +08:00
{
constexpr bool has_kw_only_args = any_of < std : : is_same < kw_only , Extra > . . . > : : value ,
has_pos_only_args = any_of < std : : is_same < pos_only , Extra > . . . > : : value ,
has_args = any_of < std : : is_same < args , Args > . . . > : : value ,
has_arg_annotations = any_of < is_keyword < Extra > . . . > : : value ;
static_assert ( has_arg_annotations | | ! has_kw_only_args , " py::kw_only requires the use of argument annotations " ) ;
static_assert ( has_arg_annotations | | ! has_pos_only_args , " py::pos_only requires the use of argument annotations (for docstrings and aligning the annotations to the argument) " ) ;
static_assert ( ! ( has_args & & has_kw_only_args ) , " py::kw_only cannot be combined with a py::args argument " ) ;
}
2020-07-23 14:58:19 +08:00
/* Generate a readable signature describing the function's arguments and return value types */
static constexpr auto signature = _ ( " ( " ) + cast_in : : arg_names + _ ( " ) -> " ) + cast_out : : name ;
PYBIND11_DESCR_CONSTEXPR auto types = decltype ( signature ) : : types ( ) ;
/* Register the function with Python from generic (non-templated) code */
initialize_generic ( rec , signature . text , types . data ( ) , sizeof . . . ( Args ) ) ;
if ( cast_in : : has_args ) rec - > has_args = true ;
if ( cast_in : : has_kwargs ) rec - > has_kwargs = true ;
/* Stash some additional information used by an important optimization in 'functional.h' */
using FunctionType = Return ( * ) ( Args . . . ) ;
constexpr bool is_function_ptr =
std : : is_convertible < Func , FunctionType > : : value & &
sizeof ( capture ) = = sizeof ( void * ) ;
if ( is_function_ptr ) {
rec - > is_stateless = true ;
rec - > data [ 1 ] = const_cast < void * > ( reinterpret_cast < const void * > ( & typeid ( FunctionType ) ) ) ;
}
}
/// Register a function call with Python (generic non-templated code goes here)
void initialize_generic ( detail : : function_record * rec , const char * text ,
const std : : type_info * const * types , size_t args ) {
/* Create copies of all referenced C-style strings */
rec - > name = strdup ( rec - > name ? rec - > name : " " ) ;
if ( rec - > doc ) rec - > doc = strdup ( rec - > doc ) ;
for ( auto & a : rec - > args ) {
if ( a . name )
a . name = strdup ( a . name ) ;
if ( a . descr )
a . descr = strdup ( a . descr ) ;
else if ( a . value )
2021-01-02 17:15:39 +08:00
a . descr = strdup ( repr ( a . value ) . cast < std : : string > ( ) . c_str ( ) ) ;
2020-07-23 14:58:19 +08:00
}
rec - > is_constructor = ! strcmp ( rec - > name , " __init__ " ) | | ! strcmp ( rec - > name , " __setstate__ " ) ;
# if !defined(NDEBUG) && !defined(PYBIND11_DISABLE_NEW_STYLE_INIT_WARNING)
if ( rec - > is_constructor & & ! rec - > is_new_style_constructor ) {
2021-01-02 17:15:39 +08:00
const auto class_name = detail : : get_fully_qualified_tp_name ( ( PyTypeObject * ) rec - > scope . ptr ( ) ) ;
2020-07-23 14:58:19 +08:00
const auto func_name = std : : string ( rec - > name ) ;
PyErr_WarnEx (
PyExc_FutureWarning ,
( " pybind11-bound class ' " + class_name + " ' is using an old-style "
" placement-new ' " + func_name + " ' which has been deprecated. See "
" the upgrade guide in pybind11's docs. This message is only visible "
" when compiled in debug mode. " ) . c_str ( ) , 0
) ;
}
# endif
/* Generate a proper function signature */
std : : string signature ;
size_t type_index = 0 , arg_index = 0 ;
for ( auto * pc = text ; * pc ! = ' \0 ' ; + + pc ) {
const auto c = * pc ;
if ( c = = ' { ' ) {
// Write arg name for everything except *args and **kwargs.
if ( * ( pc + 1 ) = = ' * ' )
continue ;
2021-01-02 17:15:39 +08:00
// Separator for keyword-only arguments, placed before the kw
// arguments start
if ( rec - > nargs_kw_only > 0 & & arg_index + rec - > nargs_kw_only = = args )
signature + = " *, " ;
2020-07-23 14:58:19 +08:00
if ( arg_index < rec - > args . size ( ) & & rec - > args [ arg_index ] . name ) {
signature + = rec - > args [ arg_index ] . name ;
} else if ( arg_index = = 0 & & rec - > is_method ) {
signature + = " self " ;
} else {
signature + = " arg " + std : : to_string ( arg_index - ( rec - > is_method ? 1 : 0 ) ) ;
}
signature + = " : " ;
} else if ( c = = ' } ' ) {
// Write default value if available.
if ( arg_index < rec - > args . size ( ) & & rec - > args [ arg_index ] . descr ) {
signature + = " = " ;
signature + = rec - > args [ arg_index ] . descr ;
}
2021-01-02 17:15:39 +08:00
// Separator for positional-only arguments (placed after the
// argument, rather than before like *
if ( rec - > nargs_pos_only > 0 & & ( arg_index + 1 ) = = rec - > nargs_pos_only )
signature + = " , / " ;
2020-07-23 14:58:19 +08:00
arg_index + + ;
} else if ( c = = ' % ' ) {
const std : : type_info * t = types [ type_index + + ] ;
if ( ! t )
pybind11_fail ( " Internal error while parsing type signature (1) " ) ;
if ( auto tinfo = detail : : get_type_info ( * t ) ) {
handle th ( ( PyObject * ) tinfo - > type ) ;
signature + =
th . attr ( " __module__ " ) . cast < std : : string > ( ) + " . " +
th . attr ( " __qualname__ " ) . cast < std : : string > ( ) ; // Python 3.3+, but we backport it to earlier versions
} else if ( rec - > is_new_style_constructor & & arg_index = = 0 ) {
// A new-style `__init__` takes `self` as `value_and_holder`.
// Rewrite it to the proper class type.
signature + =
rec - > scope . attr ( " __module__ " ) . cast < std : : string > ( ) + " . " +
rec - > scope . attr ( " __qualname__ " ) . cast < std : : string > ( ) ;
} else {
std : : string tname ( t - > name ( ) ) ;
detail : : clean_type_id ( tname ) ;
signature + = tname ;
}
} else {
signature + = c ;
}
}
2021-01-02 17:15:39 +08:00
2020-07-23 14:58:19 +08:00
if ( arg_index ! = args | | types [ type_index ] ! = nullptr )
pybind11_fail ( " Internal error while parsing type signature (2) " ) ;
# if PY_MAJOR_VERSION < 3
if ( strcmp ( rec - > name , " __next__ " ) = = 0 ) {
std : : free ( rec - > name ) ;
rec - > name = strdup ( " next " ) ;
} else if ( strcmp ( rec - > name , " __bool__ " ) = = 0 ) {
std : : free ( rec - > name ) ;
rec - > name = strdup ( " __nonzero__ " ) ;
}
# endif
rec - > signature = strdup ( signature . c_str ( ) ) ;
rec - > args . shrink_to_fit ( ) ;
rec - > nargs = ( std : : uint16_t ) args ;
if ( rec - > sibling & & PYBIND11_INSTANCE_METHOD_CHECK ( rec - > sibling . ptr ( ) ) )
rec - > sibling = PYBIND11_INSTANCE_METHOD_GET_FUNCTION ( rec - > sibling . ptr ( ) ) ;
detail : : function_record * chain = nullptr , * chain_start = rec ;
if ( rec - > sibling ) {
if ( PyCFunction_Check ( rec - > sibling . ptr ( ) ) ) {
auto rec_capsule = reinterpret_borrow < capsule > ( PyCFunction_GET_SELF ( rec - > sibling . ptr ( ) ) ) ;
chain = ( detail : : function_record * ) rec_capsule ;
/* Never append a method to an overload chain of a parent class;
instead , hide the parent ' s overloads in this case */
if ( ! chain - > scope . is ( rec - > scope ) )
chain = nullptr ;
}
// Don't trigger for things like the default __init__, which are wrapper_descriptors that we are intentionally replacing
else if ( ! rec - > sibling . is_none ( ) & & rec - > name [ 0 ] ! = ' _ ' )
pybind11_fail ( " Cannot overload existing non-function object \" " + std : : string ( rec - > name ) +
" \" with a function of the same name " ) ;
}
if ( ! chain ) {
/* No existing overload was found, create a new function object */
rec - > def = new PyMethodDef ( ) ;
std : : memset ( rec - > def , 0 , sizeof ( PyMethodDef ) ) ;
rec - > def - > ml_name = rec - > name ;
rec - > def - > ml_meth = reinterpret_cast < PyCFunction > ( reinterpret_cast < void ( * ) ( void ) > ( * dispatcher ) ) ;
rec - > def - > ml_flags = METH_VARARGS | METH_KEYWORDS ;
capsule rec_capsule ( rec , [ ] ( void * ptr ) {
destruct ( ( detail : : function_record * ) ptr ) ;
} ) ;
object scope_module ;
if ( rec - > scope ) {
if ( hasattr ( rec - > scope , " __module__ " ) ) {
scope_module = rec - > scope . attr ( " __module__ " ) ;
} else if ( hasattr ( rec - > scope , " __name__ " ) ) {
scope_module = rec - > scope . attr ( " __name__ " ) ;
}
}
m_ptr = PyCFunction_NewEx ( rec - > def , rec_capsule . ptr ( ) , scope_module . ptr ( ) ) ;
if ( ! m_ptr )
pybind11_fail ( " cpp_function::cpp_function(): Could not allocate function object " ) ;
} else {
2021-01-02 17:15:39 +08:00
/* Append at the beginning or end of the overload chain */
2020-07-23 14:58:19 +08:00
m_ptr = rec - > sibling . ptr ( ) ;
inc_ref ( ) ;
if ( chain - > is_method ! = rec - > is_method )
pybind11_fail ( " overloading a method with both static and instance methods is not supported; "
# if defined(NDEBUG)
" compile in debug mode for more details "
# else
" error while attempting to bind " + std : : string ( rec - > is_method ? " instance " : " static " ) + " method " +
std : : string ( pybind11 : : str ( rec - > scope . attr ( " __name__ " ) ) ) + " . " + std : : string ( rec - > name ) + signature
# endif
) ;
2021-01-02 17:15:39 +08:00
if ( rec - > prepend ) {
// Beginning of chain; we need to replace the capsule's current head-of-the-chain
// pointer with this one, then make this one point to the previous head of the
// chain.
chain_start = rec ;
rec - > next = chain ;
auto rec_capsule = reinterpret_borrow < capsule > ( ( ( PyCFunctionObject * ) m_ptr ) - > m_self ) ;
rec_capsule . set_pointer ( rec ) ;
} else {
// Or end of chain (normal behavior)
chain_start = chain ;
while ( chain - > next )
chain = chain - > next ;
chain - > next = rec ;
}
2020-07-23 14:58:19 +08:00
}
std : : string signatures ;
int index = 0 ;
/* Create a nice pydoc rec including all signatures and
docstrings of the functions in the overload chain */
if ( chain & & options : : show_function_signatures ( ) ) {
// First a generic signature
signatures + = rec - > name ;
signatures + = " (*args, **kwargs) \n " ;
signatures + = " Overloaded function. \n \n " ;
}
// Then specific overload signatures
bool first_user_def = true ;
for ( auto it = chain_start ; it ! = nullptr ; it = it - > next ) {
if ( options : : show_function_signatures ( ) ) {
if ( index > 0 ) signatures + = " \n " ;
if ( chain )
signatures + = std : : to_string ( + + index ) + " . " ;
signatures + = rec - > name ;
signatures + = it - > signature ;
signatures + = " \n " ;
}
if ( it - > doc & & strlen ( it - > doc ) > 0 & & options : : show_user_defined_docstrings ( ) ) {
// If we're appending another docstring, and aren't printing function signatures, we
// need to append a newline first:
if ( ! options : : show_function_signatures ( ) ) {
if ( first_user_def ) first_user_def = false ;
else signatures + = " \n " ;
}
if ( options : : show_function_signatures ( ) ) signatures + = " \n " ;
signatures + = it - > doc ;
if ( options : : show_function_signatures ( ) ) signatures + = " \n " ;
}
}
/* Install docstring */
2021-01-02 17:15:39 +08:00
auto * func = ( PyCFunctionObject * ) m_ptr ;
2020-07-23 14:58:19 +08:00
if ( func - > m_ml - > ml_doc )
std : : free ( const_cast < char * > ( func - > m_ml - > ml_doc ) ) ;
func - > m_ml - > ml_doc = strdup ( signatures . c_str ( ) ) ;
if ( rec - > is_method ) {
m_ptr = PYBIND11_INSTANCE_METHOD_NEW ( m_ptr , rec - > scope . ptr ( ) ) ;
if ( ! m_ptr )
pybind11_fail ( " cpp_function::cpp_function(): Could not allocate instance method object " ) ;
Py_DECREF ( func ) ;
}
}
/// When a cpp_function is GCed, release any memory allocated by pybind11
static void destruct ( detail : : function_record * rec ) {
2021-01-02 17:15:39 +08:00
// If on Python 3.9, check the interpreter "MICRO" (patch) version.
// If this is running on 3.9.0, we have to work around a bug.
# if !defined(PYPY_VERSION) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 9
static bool is_zero = Py_GetVersion ( ) [ 4 ] = = ' 0 ' ;
# endif
2020-07-23 14:58:19 +08:00
while ( rec ) {
detail : : function_record * next = rec - > next ;
if ( rec - > free_data )
rec - > free_data ( rec ) ;
std : : free ( ( char * ) rec - > name ) ;
std : : free ( ( char * ) rec - > doc ) ;
std : : free ( ( char * ) rec - > signature ) ;
for ( auto & arg : rec - > args ) {
std : : free ( const_cast < char * > ( arg . name ) ) ;
std : : free ( const_cast < char * > ( arg . descr ) ) ;
arg . value . dec_ref ( ) ;
}
if ( rec - > def ) {
std : : free ( const_cast < char * > ( rec - > def - > ml_doc ) ) ;
2021-01-02 17:15:39 +08:00
// Python 3.9.0 decref's these in the wrong order; rec->def
// If loaded on 3.9.0, let these leak (use Python 3.9.1 at runtime to fix)
// See https://github.com/python/cpython/pull/22670
# if !defined(PYPY_VERSION) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 9
if ( ! is_zero )
delete rec - > def ;
# else
delete rec - > def ;
# endif
2020-07-23 14:58:19 +08:00
}
delete rec ;
rec = next ;
}
}
/// Main dispatch logic for calls to functions bound using pybind11
static PyObject * dispatcher ( PyObject * self , PyObject * args_in , PyObject * kwargs_in ) {
using namespace detail ;
/* Iterator over the list of potentially admissible overloads */
const function_record * overloads = ( function_record * ) PyCapsule_GetPointer ( self , nullptr ) ,
* it = overloads ;
/* Need to know how many arguments + keyword arguments there are to pick the right overload */
2021-01-02 17:15:39 +08:00
const auto n_args_in = ( size_t ) PyTuple_GET_SIZE ( args_in ) ;
2020-07-23 14:58:19 +08:00
handle parent = n_args_in > 0 ? PyTuple_GET_ITEM ( args_in , 0 ) : nullptr ,
result = PYBIND11_TRY_NEXT_OVERLOAD ;
auto self_value_and_holder = value_and_holder ( ) ;
if ( overloads - > is_constructor ) {
const auto tinfo = get_type_info ( ( PyTypeObject * ) overloads - > scope . ptr ( ) ) ;
const auto pi = reinterpret_cast < instance * > ( parent . ptr ( ) ) ;
self_value_and_holder = pi - > get_value_and_holder ( tinfo , false ) ;
if ( ! self_value_and_holder . type | | ! self_value_and_holder . inst ) {
PyErr_SetString ( PyExc_TypeError , " __init__(self, ...) called with invalid `self` argument " ) ;
return nullptr ;
}
// If this value is already registered it must mean __init__ is invoked multiple times;
// we really can't support that in C++, so just ignore the second __init__.
if ( self_value_and_holder . instance_registered ( ) )
return none ( ) . release ( ) . ptr ( ) ;
}
try {
// We do this in two passes: in the first pass, we load arguments with `convert=false`;
// in the second, we allow conversion (except for arguments with an explicit
// py::arg().noconvert()). This lets us prefer calls without conversion, with
// conversion as a fallback.
std : : vector < function_call > second_pass ;
// However, if there are no overloads, we can just skip the no-convert pass entirely
const bool overloaded = it ! = nullptr & & it - > next ! = nullptr ;
for ( ; it ! = nullptr ; it = it - > next ) {
/* For each overload:
1. Copy all positional arguments we were given , also checking to make sure that
named positional arguments weren ' t * also * specified via kwarg .
2. If we weren ' t given enough , try to make up the omitted ones by checking
whether they were provided by a kwarg matching the ` py : : arg ( " name " ) ` name . If
so , use it ( and remove it from kwargs ; if not , see if the function binding
provided a default that we can use .
3. Ensure that either all keyword arguments were " consumed " , or that the function
takes a kwargs argument to accept unconsumed kwargs .
4. Any positional arguments still left get put into a tuple ( for args ) , and any
leftover kwargs get put into a dict .
5. Pack everything into a vector ; if we have py : : args or py : : kwargs , they are an
extra tuple or dict at the end of the positional arguments .
6. Call the function call dispatcher ( function_record : : impl )
If one of these fail , move on to the next overload and keep trying until we get a
result other than PYBIND11_TRY_NEXT_OVERLOAD .
*/
const function_record & func = * it ;
2021-01-02 17:15:39 +08:00
size_t num_args = func . nargs ; // Number of positional arguments that we need
if ( func . has_args ) - - num_args ; // (but don't count py::args
if ( func . has_kwargs ) - - num_args ; // or py::kwargs)
size_t pos_args = num_args - func . nargs_kw_only ;
2020-07-23 14:58:19 +08:00
if ( ! func . has_args & & n_args_in > pos_args )
2021-01-02 17:15:39 +08:00
continue ; // Too many positional arguments for this overload
2020-07-23 14:58:19 +08:00
if ( n_args_in < pos_args & & func . args . size ( ) < pos_args )
2021-01-02 17:15:39 +08:00
continue ; // Not enough positional arguments given, and not enough defaults to fill in the blanks
2020-07-23 14:58:19 +08:00
function_call call ( func , parent ) ;
size_t args_to_copy = ( std : : min ) ( pos_args , n_args_in ) ; // Protect std::min with parentheses
size_t args_copied = 0 ;
// 0. Inject new-style `self` argument
if ( func . is_new_style_constructor ) {
// The `value` may have been preallocated by an old-style `__init__`
// if it was a preceding candidate for overload resolution.
if ( self_value_and_holder )
self_value_and_holder . type - > dealloc ( self_value_and_holder ) ;
call . init_self = PyTuple_GET_ITEM ( args_in , 0 ) ;
2021-01-02 17:15:39 +08:00
call . args . emplace_back ( reinterpret_cast < PyObject * > ( & self_value_and_holder ) ) ;
2020-07-23 14:58:19 +08:00
call . args_convert . push_back ( false ) ;
+ + args_copied ;
}
// 1. Copy any position arguments given.
bool bad_arg = false ;
for ( ; args_copied < args_to_copy ; + + args_copied ) {
const argument_record * arg_rec = args_copied < func . args . size ( ) ? & func . args [ args_copied ] : nullptr ;
if ( kwargs_in & & arg_rec & & arg_rec - > name & & PyDict_GetItemString ( kwargs_in , arg_rec - > name ) ) {
bad_arg = true ;
break ;
}
handle arg ( PyTuple_GET_ITEM ( args_in , args_copied ) ) ;
if ( arg_rec & & ! arg_rec - > none & & arg . is_none ( ) ) {
bad_arg = true ;
break ;
}
call . args . push_back ( arg ) ;
call . args_convert . push_back ( arg_rec ? arg_rec - > convert : true ) ;
}
if ( bad_arg )
continue ; // Maybe it was meant for another overload (issue #688)
// We'll need to copy this if we steal some kwargs for defaults
dict kwargs = reinterpret_borrow < dict > ( kwargs_in ) ;
2021-01-02 17:15:39 +08:00
// 1.5. Fill in any missing pos_only args from defaults if they exist
if ( args_copied < func . nargs_pos_only ) {
for ( ; args_copied < func . nargs_pos_only ; + + args_copied ) {
const auto & arg_rec = func . args [ args_copied ] ;
handle value ;
if ( arg_rec . value ) {
value = arg_rec . value ;
}
if ( value ) {
call . args . push_back ( value ) ;
call . args_convert . push_back ( arg_rec . convert ) ;
} else
break ;
}
if ( args_copied < func . nargs_pos_only )
continue ; // Not enough defaults to fill the positional arguments
}
2020-07-23 14:58:19 +08:00
// 2. Check kwargs and, failing that, defaults that may help complete the list
2021-01-02 17:15:39 +08:00
if ( args_copied < num_args ) {
2020-07-23 14:58:19 +08:00
bool copied_kwargs = false ;
2021-01-02 17:15:39 +08:00
for ( ; args_copied < num_args ; + + args_copied ) {
const auto & arg_rec = func . args [ args_copied ] ;
2020-07-23 14:58:19 +08:00
handle value ;
2021-01-02 17:15:39 +08:00
if ( kwargs_in & & arg_rec . name )
value = PyDict_GetItemString ( kwargs . ptr ( ) , arg_rec . name ) ;
2020-07-23 14:58:19 +08:00
if ( value ) {
// Consume a kwargs value
if ( ! copied_kwargs ) {
kwargs = reinterpret_steal < dict > ( PyDict_Copy ( kwargs . ptr ( ) ) ) ;
copied_kwargs = true ;
}
2021-01-02 17:15:39 +08:00
PyDict_DelItemString ( kwargs . ptr ( ) , arg_rec . name ) ;
} else if ( arg_rec . value ) {
value = arg_rec . value ;
}
if ( ! arg_rec . none & & value . is_none ( ) ) {
break ;
2020-07-23 14:58:19 +08:00
}
if ( value ) {
call . args . push_back ( value ) ;
2021-01-02 17:15:39 +08:00
call . args_convert . push_back ( arg_rec . convert ) ;
2020-07-23 14:58:19 +08:00
}
else
break ;
}
2021-01-02 17:15:39 +08:00
if ( args_copied < num_args )
2020-07-23 14:58:19 +08:00
continue ; // Not enough arguments, defaults, or kwargs to fill the positional arguments
}
// 3. Check everything was consumed (unless we have a kwargs arg)
2021-01-02 17:15:39 +08:00
if ( kwargs & & ! kwargs . empty ( ) & & ! func . has_kwargs )
2020-07-23 14:58:19 +08:00
continue ; // Unconsumed kwargs, but no py::kwargs argument to accept them
// 4a. If we have a py::args argument, create a new tuple with leftovers
if ( func . has_args ) {
tuple extra_args ;
if ( args_to_copy = = 0 ) {
// We didn't copy out any position arguments from the args_in tuple, so we
// can reuse it directly without copying:
extra_args = reinterpret_borrow < tuple > ( args_in ) ;
} else if ( args_copied > = n_args_in ) {
extra_args = tuple ( 0 ) ;
} else {
size_t args_size = n_args_in - args_copied ;
extra_args = tuple ( args_size ) ;
for ( size_t i = 0 ; i < args_size ; + + i ) {
extra_args [ i ] = PyTuple_GET_ITEM ( args_in , args_copied + i ) ;
}
}
call . args . push_back ( extra_args ) ;
call . args_convert . push_back ( false ) ;
call . args_ref = std : : move ( extra_args ) ;
}
// 4b. If we have a py::kwargs, pass on any remaining kwargs
if ( func . has_kwargs ) {
if ( ! kwargs . ptr ( ) )
kwargs = dict ( ) ; // If we didn't get one, send an empty one
call . args . push_back ( kwargs ) ;
call . args_convert . push_back ( false ) ;
call . kwargs_ref = std : : move ( kwargs ) ;
}
// 5. Put everything in a vector. Not technically step 5, we've been building it
// in `call.args` all along.
# if !defined(NDEBUG)
if ( call . args . size ( ) ! = func . nargs | | call . args_convert . size ( ) ! = func . nargs )
pybind11_fail ( " Internal error: function call dispatcher inserted wrong number of arguments! " ) ;
# endif
std : : vector < bool > second_pass_convert ;
if ( overloaded ) {
// We're in the first no-convert pass, so swap out the conversion flags for a
// set of all-false flags. If the call fails, we'll swap the flags back in for
// the conversion-allowed call below.
second_pass_convert . resize ( func . nargs , false ) ;
call . args_convert . swap ( second_pass_convert ) ;
}
// 6. Call the function.
try {
loader_life_support guard { } ;
result = func . impl ( call ) ;
} catch ( reference_cast_error & ) {
result = PYBIND11_TRY_NEXT_OVERLOAD ;
}
if ( result . ptr ( ) ! = PYBIND11_TRY_NEXT_OVERLOAD )
break ;
if ( overloaded ) {
// The (overloaded) call failed; if the call has at least one argument that
// permits conversion (i.e. it hasn't been explicitly specified `.noconvert()`)
// then add this call to the list of second pass overloads to try.
for ( size_t i = func . is_method ? 1 : 0 ; i < pos_args ; i + + ) {
if ( second_pass_convert [ i ] ) {
// Found one: swap the converting flags back in and store the call for
// the second pass.
call . args_convert . swap ( second_pass_convert ) ;
second_pass . push_back ( std : : move ( call ) ) ;
break ;
}
}
}
}
if ( overloaded & & ! second_pass . empty ( ) & & result . ptr ( ) = = PYBIND11_TRY_NEXT_OVERLOAD ) {
// The no-conversion pass finished without success, try again with conversion allowed
for ( auto & call : second_pass ) {
try {
loader_life_support guard { } ;
result = call . func . impl ( call ) ;
} catch ( reference_cast_error & ) {
result = PYBIND11_TRY_NEXT_OVERLOAD ;
}
if ( result . ptr ( ) ! = PYBIND11_TRY_NEXT_OVERLOAD ) {
// The error reporting logic below expects 'it' to be valid, as it would be
// if we'd encountered this failure in the first-pass loop.
if ( ! result )
it = & call . func ;
break ;
}
}
}
} catch ( error_already_set & e ) {
e . restore ( ) ;
return nullptr ;
2021-01-02 17:15:39 +08:00
# ifdef __GLIBCXX__
2020-07-23 14:58:19 +08:00
} catch ( abi : : __forced_unwind & ) {
throw ;
# endif
} catch ( . . . ) {
/* When an exception is caught, give each registered exception
translator a chance to translate it to a Python exception
in reverse order of registration .
A translator may choose to do one of the following :
- catch the exception and call PyErr_SetString or PyErr_SetObject
to set a standard ( or custom ) Python exception , or
- do nothing and let the exception fall through to the next translator , or
- delegate translation to the next translator by throwing a new type of exception . */
auto last_exception = std : : current_exception ( ) ;
auto & registered_exception_translators = get_internals ( ) . registered_exception_translators ;
for ( auto & translator : registered_exception_translators ) {
try {
translator ( last_exception ) ;
} catch ( . . . ) {
last_exception = std : : current_exception ( ) ;
continue ;
}
return nullptr ;
}
PyErr_SetString ( PyExc_SystemError , " Exception escaped from default exception translator! " ) ;
return nullptr ;
}
auto append_note_if_missing_header_is_suspected = [ ] ( std : : string & msg ) {
if ( msg . find ( " std:: " ) ! = std : : string : : npos ) {
msg + = " \n \n "
" Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>, \n "
" <pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic \n "
" conversions are optional and require extra headers to be included \n "
" when compiling your pybind11 module. " ;
}
} ;
if ( result . ptr ( ) = = PYBIND11_TRY_NEXT_OVERLOAD ) {
if ( overloads - > is_operator )
return handle ( Py_NotImplemented ) . inc_ref ( ) . ptr ( ) ;
std : : string msg = std : : string ( overloads - > name ) + " (): incompatible " +
std : : string ( overloads - > is_constructor ? " constructor " : " function " ) +
" arguments. The following argument types are supported: \n " ;
int ctr = 0 ;
for ( const function_record * it2 = overloads ; it2 ! = nullptr ; it2 = it2 - > next ) {
msg + = " " + std : : to_string ( + + ctr ) + " . " ;
bool wrote_sig = false ;
if ( overloads - > is_constructor ) {
// For a constructor, rewrite `(self: Object, arg0, ...) -> NoneType` as `Object(arg0, ...)`
std : : string sig = it2 - > signature ;
size_t start = sig . find ( ' ( ' ) + 7 ; // skip "(self: "
if ( start < sig . size ( ) ) {
// End at the , for the next argument
size_t end = sig . find ( " , " ) , next = end + 2 ;
size_t ret = sig . rfind ( " -> " ) ;
// Or the ), if there is no comma:
if ( end > = sig . size ( ) ) next = end = sig . find ( ' ) ' ) ;
if ( start < end & & next < sig . size ( ) ) {
msg . append ( sig , start , end - start ) ;
msg + = ' ( ' ;
msg . append ( sig , next , ret - next ) ;
wrote_sig = true ;
}
}
}
if ( ! wrote_sig ) msg + = it2 - > signature ;
msg + = " \n " ;
}
msg + = " \n Invoked with: " ;
auto args_ = reinterpret_borrow < tuple > ( args_in ) ;
bool some_args = false ;
for ( size_t ti = overloads - > is_constructor ? 1 : 0 ; ti < args_ . size ( ) ; + + ti ) {
if ( ! some_args ) some_args = true ;
else msg + = " , " ;
2021-01-02 17:15:39 +08:00
try {
msg + = pybind11 : : repr ( args_ [ ti ] ) ;
} catch ( const error_already_set & ) {
msg + = " <repr raised Error> " ;
}
2020-07-23 14:58:19 +08:00
}
if ( kwargs_in ) {
auto kwargs = reinterpret_borrow < dict > ( kwargs_in ) ;
2021-01-02 17:15:39 +08:00
if ( ! kwargs . empty ( ) ) {
2020-07-23 14:58:19 +08:00
if ( some_args ) msg + = " ; " ;
msg + = " kwargs: " ;
bool first = true ;
for ( auto kwarg : kwargs ) {
if ( first ) first = false ;
else msg + = " , " ;
2021-01-02 17:15:39 +08:00
msg + = pybind11 : : str ( " {}= " ) . format ( kwarg . first ) ;
try {
msg + = pybind11 : : repr ( kwarg . second ) ;
} catch ( const error_already_set & ) {
msg + = " <repr raised Error> " ;
}
2020-07-23 14:58:19 +08:00
}
}
}
append_note_if_missing_header_is_suspected ( msg ) ;
PyErr_SetString ( PyExc_TypeError , msg . c_str ( ) ) ;
return nullptr ;
} else if ( ! result ) {
std : : string msg = " Unable to convert function return value to a "
" Python type! The signature was \n \t " ;
msg + = it - > signature ;
append_note_if_missing_header_is_suspected ( msg ) ;
PyErr_SetString ( PyExc_TypeError , msg . c_str ( ) ) ;
return nullptr ;
} else {
if ( overloads - > is_constructor & & ! self_value_and_holder . holder_constructed ( ) ) {
auto * pi = reinterpret_cast < instance * > ( parent . ptr ( ) ) ;
self_value_and_holder . type - > init_instance ( pi , nullptr ) ;
}
return result . ptr ( ) ;
}
}
} ;
/// Wrapper for Python extension modules
2021-01-02 17:15:39 +08:00
class module_ : public object {
2020-07-23 14:58:19 +08:00
public :
2021-01-02 17:15:39 +08:00
PYBIND11_OBJECT_DEFAULT ( module_ , object , PyModule_Check )
2020-07-23 14:58:19 +08:00
/// Create a new top-level Python module with the given name and docstring
2021-01-02 17:15:39 +08:00
PYBIND11_DEPRECATED ( " Use PYBIND11_MODULE or module_::create_extension_module instead " )
explicit module_ ( const char * name , const char * doc = nullptr ) {
2020-07-23 14:58:19 +08:00
# if PY_MAJOR_VERSION >= 3
2021-01-02 17:15:39 +08:00
* this = create_extension_module ( name , doc , new PyModuleDef ( ) ) ;
2020-07-23 14:58:19 +08:00
# else
2021-01-02 17:15:39 +08:00
* this = create_extension_module ( name , doc , nullptr ) ;
2020-07-23 14:58:19 +08:00
# endif
}
/** \rst
Create Python binding for a new function within the module scope . ` ` Func ` `
can be a plain C + + function , a function pointer , or a lambda function . For
details on the ` ` Extra & & . . . extra ` ` argument , see section : ref : ` extras ` .
\ endrst */
template < typename Func , typename . . . Extra >
2021-01-02 17:15:39 +08:00
module_ & def ( const char * name_ , Func & & f , const Extra & . . . extra ) {
2020-07-23 14:58:19 +08:00
cpp_function func ( std : : forward < Func > ( f ) , name ( name_ ) , scope ( * this ) ,
sibling ( getattr ( * this , name_ , none ( ) ) ) , extra . . . ) ;
// NB: allow overwriting here because cpp_function sets up a chain with the intention of
// overwriting (and has already checked internally that it isn't overwriting non-functions).
add_object ( name_ , func , true /* overwrite */ ) ;
return * this ;
}
/** \rst
Create and return a new Python submodule with the given name and docstring .
This also works recursively , i . e .
. . code - block : : cpp
2021-01-02 17:15:39 +08:00
py : : module_ m ( " example " , " pybind11 example plugin " ) ;
py : : module_ m2 = m . def_submodule ( " sub " , " A submodule of 'example' " ) ;
py : : module_ m3 = m2 . def_submodule ( " subsub " , " A submodule of 'example.sub' " ) ;
2020-07-23 14:58:19 +08:00
\ endrst */
2021-01-02 17:15:39 +08:00
module_ def_submodule ( const char * name , const char * doc = nullptr ) {
2020-07-23 14:58:19 +08:00
std : : string full_name = std : : string ( PyModule_GetName ( m_ptr ) )
+ std : : string ( " . " ) + std : : string ( name ) ;
2021-01-02 17:15:39 +08:00
auto result = reinterpret_borrow < module_ > ( PyImport_AddModule ( full_name . c_str ( ) ) ) ;
2020-07-23 14:58:19 +08:00
if ( doc & & options : : show_user_defined_docstrings ( ) )
result . attr ( " __doc__ " ) = pybind11 : : str ( doc ) ;
attr ( name ) = result ;
return result ;
}
/// Import and return a module or throws `error_already_set`.
2021-01-02 17:15:39 +08:00
static module_ import ( const char * name ) {
2020-07-23 14:58:19 +08:00
PyObject * obj = PyImport_ImportModule ( name ) ;
if ( ! obj )
throw error_already_set ( ) ;
2021-01-02 17:15:39 +08:00
return reinterpret_steal < module_ > ( obj ) ;
2020-07-23 14:58:19 +08:00
}
/// Reload the module or throws `error_already_set`.
void reload ( ) {
PyObject * obj = PyImport_ReloadModule ( ptr ( ) ) ;
if ( ! obj )
throw error_already_set ( ) ;
2021-01-02 17:15:39 +08:00
* this = reinterpret_steal < module_ > ( obj ) ;
2020-07-23 14:58:19 +08:00
}
2021-01-02 17:15:39 +08:00
/** \rst
Adds an object to the module using the given name . Throws if an object with the given name
already exists .
` ` overwrite ` ` should almost always be false : attempting to overwrite objects that pybind11 has
established will , in most cases , break things .
\ endrst */
2020-07-23 14:58:19 +08:00
PYBIND11_NOINLINE void add_object ( const char * name , handle obj , bool overwrite = false ) {
if ( ! overwrite & & hasattr ( * this , name ) )
pybind11_fail ( " Error during initialization: multiple incompatible definitions with name \" " +
std : : string ( name ) + " \" " ) ;
PyModule_AddObject ( ptr ( ) , name , obj . inc_ref ( ) . ptr ( ) /* steals a reference */ ) ;
}
2021-01-02 17:15:39 +08:00
# if PY_MAJOR_VERSION >= 3
using module_def = PyModuleDef ;
# else
struct module_def { } ;
# endif
/** \rst
Create a new top - level module that can be used as the main module of a C extension .
For Python 3 , ` ` def ` ` should point to a staticly allocated module_def .
For Python 2 , ` ` def ` ` can be a nullptr and is completely ignored .
\ endrst */
static module_ create_extension_module ( const char * name , const char * doc , module_def * def ) {
# if PY_MAJOR_VERSION >= 3
// module_def is PyModuleDef
def = new ( def ) PyModuleDef { // Placement new (not an allocation).
/* m_base */ PyModuleDef_HEAD_INIT ,
/* m_name */ name ,
/* m_doc */ options : : show_user_defined_docstrings ( ) ? doc : nullptr ,
/* m_size */ - 1 ,
/* m_methods */ nullptr ,
/* m_slots */ nullptr ,
/* m_traverse */ nullptr ,
/* m_clear */ nullptr ,
/* m_free */ nullptr
} ;
auto m = PyModule_Create ( def ) ;
# else
// Ignore module_def *def; only necessary for Python 3
( void ) def ;
auto m = Py_InitModule3 ( name , nullptr , options : : show_user_defined_docstrings ( ) ? doc : nullptr ) ;
# endif
if ( m = = nullptr ) {
if ( PyErr_Occurred ( ) )
throw error_already_set ( ) ;
pybind11_fail ( " Internal error in module_::create_extension_module() " ) ;
}
// TODO: Sould be reinterpret_steal for Python 3, but Python also steals it again when returned from PyInit_...
// For Python 2, reinterpret_borrow is correct.
return reinterpret_borrow < module_ > ( m ) ;
}
2020-07-23 14:58:19 +08:00
} ;
2021-01-02 17:15:39 +08:00
// When inside a namespace (or anywhere as long as it's not the first item on a line),
// C++20 allows "module" to be used. This is provided for backward compatibility, and for
// simplicity, if someone wants to use py::module for example, that is perfectly safe.
using module = module_ ;
2020-07-23 14:58:19 +08:00
/// \ingroup python_builtins
/// Return a dictionary representing the global variables in the current execution frame,
/// or ``__main__.__dict__`` if there is no frame (usually when the interpreter is embedded).
inline dict globals ( ) {
PyObject * p = PyEval_GetGlobals ( ) ;
2021-01-02 17:15:39 +08:00
return reinterpret_borrow < dict > ( p ? p : module_ : : import ( " __main__ " ) . attr ( " __dict__ " ) . ptr ( ) ) ;
2020-07-23 14:58:19 +08:00
}
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_BEGIN ( detail )
2020-07-23 14:58:19 +08:00
/// Generic support for creating new Python heap types
class generic_type : public object {
public :
PYBIND11_OBJECT_DEFAULT ( generic_type , object , PyType_Check )
protected :
void initialize ( const type_record & rec ) {
2021-01-02 17:15:39 +08:00
if ( rec . scope & & hasattr ( rec . scope , " __dict__ " ) & & rec . scope . attr ( " __dict__ " ) . contains ( rec . name ) )
2020-07-23 14:58:19 +08:00
pybind11_fail ( " generic_type: cannot initialize type \" " + std : : string ( rec . name ) +
" \" : an object with that name is already defined " ) ;
if ( rec . module_local ? get_local_type_info ( * rec . type ) : get_global_type_info ( * rec . type ) )
pybind11_fail ( " generic_type: type \" " + std : : string ( rec . name ) +
" \" is already registered! " ) ;
m_ptr = make_new_python_type ( rec ) ;
/* Register supplemental type information in C++ dict */
auto * tinfo = new detail : : type_info ( ) ;
tinfo - > type = ( PyTypeObject * ) m_ptr ;
tinfo - > cpptype = rec . type ;
tinfo - > type_size = rec . type_size ;
tinfo - > type_align = rec . type_align ;
tinfo - > operator_new = rec . operator_new ;
tinfo - > holder_size_in_ptrs = size_in_ptrs ( rec . holder_size ) ;
tinfo - > init_instance = rec . init_instance ;
tinfo - > dealloc = rec . dealloc ;
tinfo - > simple_type = true ;
tinfo - > simple_ancestors = true ;
tinfo - > default_holder = rec . default_holder ;
tinfo - > module_local = rec . module_local ;
auto & internals = get_internals ( ) ;
auto tindex = std : : type_index ( * rec . type ) ;
tinfo - > direct_conversions = & internals . direct_conversions [ tindex ] ;
if ( rec . module_local )
registered_local_types_cpp ( ) [ tindex ] = tinfo ;
else
internals . registered_types_cpp [ tindex ] = tinfo ;
internals . registered_types_py [ ( PyTypeObject * ) m_ptr ] = { tinfo } ;
if ( rec . bases . size ( ) > 1 | | rec . multiple_inheritance ) {
mark_parents_nonsimple ( tinfo - > type ) ;
tinfo - > simple_ancestors = false ;
}
else if ( rec . bases . size ( ) = = 1 ) {
auto parent_tinfo = get_type_info ( ( PyTypeObject * ) rec . bases [ 0 ] . ptr ( ) ) ;
tinfo - > simple_ancestors = parent_tinfo - > simple_ancestors ;
}
if ( rec . module_local ) {
// Stash the local typeinfo and loader so that external modules can access it.
tinfo - > module_local_load = & type_caster_generic : : local_load ;
setattr ( m_ptr , PYBIND11_MODULE_LOCAL_ID , capsule ( tinfo ) ) ;
}
}
/// Helper function which tags all parents of a type using mult. inheritance
void mark_parents_nonsimple ( PyTypeObject * value ) {
auto t = reinterpret_borrow < tuple > ( value - > tp_bases ) ;
for ( handle h : t ) {
auto tinfo2 = get_type_info ( ( PyTypeObject * ) h . ptr ( ) ) ;
if ( tinfo2 )
tinfo2 - > simple_type = false ;
mark_parents_nonsimple ( ( PyTypeObject * ) h . ptr ( ) ) ;
}
}
void install_buffer_funcs (
buffer_info * ( * get_buffer ) ( PyObject * , void * ) ,
void * get_buffer_data ) {
2021-01-02 17:15:39 +08:00
auto * type = ( PyHeapTypeObject * ) m_ptr ;
2020-07-23 14:58:19 +08:00
auto tinfo = detail : : get_type_info ( & type - > ht_type ) ;
if ( ! type - > ht_type . tp_as_buffer )
pybind11_fail (
" To be able to register buffer protocol support for the type ' " +
2021-01-02 17:15:39 +08:00
get_fully_qualified_tp_name ( tinfo - > type ) +
2020-07-23 14:58:19 +08:00
" ' the associated class<>(..) invocation must "
" include the pybind11::buffer_protocol() annotation! " ) ;
tinfo - > get_buffer = get_buffer ;
tinfo - > get_buffer_data = get_buffer_data ;
}
// rec_func must be set for either fget or fset.
void def_property_static_impl ( const char * name ,
handle fget , handle fset ,
detail : : function_record * rec_func ) {
const auto is_static = rec_func & & ! ( rec_func - > is_method & & rec_func - > scope ) ;
const auto has_doc = rec_func & & rec_func - > doc & & pybind11 : : options : : show_user_defined_docstrings ( ) ;
auto property = handle ( ( PyObject * ) ( is_static ? get_internals ( ) . static_property_type
: & PyProperty_Type ) ) ;
attr ( name ) = property ( fget . ptr ( ) ? fget : none ( ) ,
fset . ptr ( ) ? fset : none ( ) ,
/*deleter*/ none ( ) ,
pybind11 : : str ( has_doc ? rec_func - > doc : " " ) ) ;
}
} ;
/// Set the pointer to operator new if it exists. The cast is needed because it can be overloaded.
template < typename T , typename = void_t < decltype ( static_cast < void * ( * ) ( size_t ) > ( T : : operator new ) ) > >
void set_operator_new ( type_record * r ) { r - > operator_new = & T : : operator new ; }
template < typename > void set_operator_new ( . . . ) { }
template < typename T , typename SFINAE = void > struct has_operator_delete : std : : false_type { } ;
template < typename T > struct has_operator_delete < T , void_t < decltype ( static_cast < void ( * ) ( void * ) > ( T : : operator delete ) ) > >
: std : : true_type { } ;
template < typename T , typename SFINAE = void > struct has_operator_delete_size : std : : false_type { } ;
template < typename T > struct has_operator_delete_size < T , void_t < decltype ( static_cast < void ( * ) ( void * , size_t ) > ( T : : operator delete ) ) > >
: std : : true_type { } ;
/// Call class-specific delete if it exists or global otherwise. Can also be an overload set.
template < typename T , enable_if_t < has_operator_delete < T > : : value , int > = 0 >
void call_operator_delete ( T * p , size_t , size_t ) { T : : operator delete ( p ) ; }
template < typename T , enable_if_t < ! has_operator_delete < T > : : value & & has_operator_delete_size < T > : : value , int > = 0 >
void call_operator_delete ( T * p , size_t s , size_t ) { T : : operator delete ( p , s ) ; }
inline void call_operator_delete ( void * p , size_t s , size_t a ) {
( void ) s ; ( void ) a ;
# if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
if ( a > __STDCPP_DEFAULT_NEW_ALIGNMENT__ ) {
# ifdef __cpp_sized_deallocation
: : operator delete ( p , s , std : : align_val_t ( a ) ) ;
# else
: : operator delete ( p , std : : align_val_t ( a ) ) ;
# endif
return ;
}
# endif
# ifdef __cpp_sized_deallocation
: : operator delete ( p , s ) ;
# else
: : operator delete ( p ) ;
# endif
}
2021-01-02 17:15:39 +08:00
inline void add_class_method ( object & cls , const char * name_ , const cpp_function & cf ) {
cls . attr ( cf . name ( ) ) = cf ;
if ( strcmp ( name_ , " __eq__ " ) = = 0 & & ! cls . attr ( " __dict__ " ) . contains ( " __hash__ " ) ) {
cls . attr ( " __hash__ " ) = none ( ) ;
}
}
PYBIND11_NAMESPACE_END ( detail )
2020-07-23 14:58:19 +08:00
/// Given a pointer to a member function, cast it to its `Derived` version.
/// Forward everything else unchanged.
template < typename /*Derived*/ , typename F >
auto method_adaptor ( F & & f ) - > decltype ( std : : forward < F > ( f ) ) { return std : : forward < F > ( f ) ; }
template < typename Derived , typename Return , typename Class , typename . . . Args >
auto method_adaptor ( Return ( Class : : * pmf ) ( Args . . . ) ) - > Return ( Derived : : * ) ( Args . . . ) {
static_assert ( detail : : is_accessible_base_of < Class , Derived > : : value ,
" Cannot bind an inaccessible base class method; use a lambda definition instead " ) ;
return pmf ;
}
template < typename Derived , typename Return , typename Class , typename . . . Args >
auto method_adaptor ( Return ( Class : : * pmf ) ( Args . . . ) const ) - > Return ( Derived : : * ) ( Args . . . ) const {
static_assert ( detail : : is_accessible_base_of < Class , Derived > : : value ,
" Cannot bind an inaccessible base class method; use a lambda definition instead " ) ;
return pmf ;
}
template < typename type_ , typename . . . options >
class class_ : public detail : : generic_type {
template < typename T > using is_holder = detail : : is_holder_type < type_ , T > ;
template < typename T > using is_subtype = detail : : is_strict_base_of < type_ , T > ;
template < typename T > using is_base = detail : : is_strict_base_of < T , type_ > ;
// struct instead of using here to help MSVC:
template < typename T > struct is_valid_class_option :
detail : : any_of < is_holder < T > , is_subtype < T > , is_base < T > > { } ;
public :
using type = type_ ;
using type_alias = detail : : exactly_one_t < is_subtype , void , options . . . > ;
constexpr static bool has_alias = ! std : : is_void < type_alias > : : value ;
using holder_type = detail : : exactly_one_t < is_holder , std : : unique_ptr < type > , options . . . > ;
static_assert ( detail : : all_of < is_valid_class_option < options > . . . > : : value ,
" Unknown/invalid class_ template parameters provided " ) ;
static_assert ( ! has_alias | | std : : is_polymorphic < type > : : value ,
" Cannot use an alias class with a non-polymorphic type " ) ;
PYBIND11_OBJECT ( class_ , generic_type , PyType_Check )
template < typename . . . Extra >
class_ ( handle scope , const char * name , const Extra & . . . extra ) {
using namespace detail ;
// MI can only be specified via class_ template options, not constructor parameters
static_assert (
none_of < is_pyobject < Extra > . . . > : : value | | // no base class arguments, or:
( constexpr_sum ( is_pyobject < Extra > : : value . . . ) = = 1 & & // Exactly one base
constexpr_sum ( is_base < options > : : value . . . ) = = 0 & & // no template option bases
none_of < std : : is_same < multiple_inheritance , Extra > . . . > : : value ) , // no multiple_inheritance attr
" Error: multiple inheritance bases must be specified via class_ template options " ) ;
type_record record ;
record . scope = scope ;
record . name = name ;
record . type = & typeid ( type ) ;
record . type_size = sizeof ( conditional_t < has_alias , type_alias , type > ) ;
record . type_align = alignof ( conditional_t < has_alias , type_alias , type > & ) ;
record . holder_size = sizeof ( holder_type ) ;
record . init_instance = init_instance ;
record . dealloc = dealloc ;
record . default_holder = detail : : is_instantiation < std : : unique_ptr , holder_type > : : value ;
set_operator_new < type > ( & record ) ;
/* Register base classes specified via template arguments to class_, if any */
PYBIND11_EXPAND_SIDE_EFFECTS ( add_base < options > ( record ) ) ;
/* Process optional arguments, if any */
process_attributes < Extra . . . > : : init ( extra . . . , & record ) ;
generic_type : : initialize ( record ) ;
if ( has_alias ) {
auto & instances = record . module_local ? registered_local_types_cpp ( ) : get_internals ( ) . registered_types_cpp ;
instances [ std : : type_index ( typeid ( type_alias ) ) ] = instances [ std : : type_index ( typeid ( type ) ) ] ;
}
}
template < typename Base , detail : : enable_if_t < is_base < Base > : : value , int > = 0 >
static void add_base ( detail : : type_record & rec ) {
rec . add_base ( typeid ( Base ) , [ ] ( void * src ) - > void * {
return static_cast < Base * > ( reinterpret_cast < type * > ( src ) ) ;
} ) ;
}
template < typename Base , detail : : enable_if_t < ! is_base < Base > : : value , int > = 0 >
static void add_base ( detail : : type_record & ) { }
template < typename Func , typename . . . Extra >
class_ & def ( const char * name_ , Func & & f , const Extra & . . . extra ) {
cpp_function cf ( method_adaptor < type > ( std : : forward < Func > ( f ) ) , name ( name_ ) , is_method ( * this ) ,
sibling ( getattr ( * this , name_ , none ( ) ) ) , extra . . . ) ;
2021-01-02 17:15:39 +08:00
add_class_method ( * this , name_ , cf ) ;
2020-07-23 14:58:19 +08:00
return * this ;
}
template < typename Func , typename . . . Extra > class_ &
def_static ( const char * name_ , Func & & f , const Extra & . . . extra ) {
static_assert ( ! std : : is_member_function_pointer < Func > : : value ,
" def_static(...) called with a non-static member function pointer " ) ;
cpp_function cf ( std : : forward < Func > ( f ) , name ( name_ ) , scope ( * this ) ,
sibling ( getattr ( * this , name_ , none ( ) ) ) , extra . . . ) ;
attr ( cf . name ( ) ) = staticmethod ( cf ) ;
return * this ;
}
template < detail : : op_id id , detail : : op_type ot , typename L , typename R , typename . . . Extra >
class_ & def ( const detail : : op_ < id , ot , L , R > & op , const Extra & . . . extra ) {
op . execute ( * this , extra . . . ) ;
return * this ;
}
template < detail : : op_id id , detail : : op_type ot , typename L , typename R , typename . . . Extra >
class_ & def_cast ( const detail : : op_ < id , ot , L , R > & op , const Extra & . . . extra ) {
op . execute_cast ( * this , extra . . . ) ;
return * this ;
}
template < typename . . . Args , typename . . . Extra >
class_ & def ( const detail : : initimpl : : constructor < Args . . . > & init , const Extra & . . . extra ) {
init . execute ( * this , extra . . . ) ;
return * this ;
}
template < typename . . . Args , typename . . . Extra >
class_ & def ( const detail : : initimpl : : alias_constructor < Args . . . > & init , const Extra & . . . extra ) {
init . execute ( * this , extra . . . ) ;
return * this ;
}
template < typename . . . Args , typename . . . Extra >
class_ & def ( detail : : initimpl : : factory < Args . . . > & & init , const Extra & . . . extra ) {
std : : move ( init ) . execute ( * this , extra . . . ) ;
return * this ;
}
template < typename . . . Args , typename . . . Extra >
class_ & def ( detail : : initimpl : : pickle_factory < Args . . . > & & pf , const Extra & . . . extra ) {
std : : move ( pf ) . execute ( * this , extra . . . ) ;
return * this ;
}
2021-01-02 17:15:39 +08:00
template < typename Func >
class_ & def_buffer ( Func & & func ) {
2020-07-23 14:58:19 +08:00
struct capture { Func func ; } ;
2021-01-02 17:15:39 +08:00
auto * ptr = new capture { std : : forward < Func > ( func ) } ;
2020-07-23 14:58:19 +08:00
install_buffer_funcs ( [ ] ( PyObject * obj , void * ptr ) - > buffer_info * {
detail : : make_caster < type > caster ;
if ( ! caster . load ( obj , false ) )
return nullptr ;
return new buffer_info ( ( ( capture * ) ptr ) - > func ( caster ) ) ;
} , ptr ) ;
2021-01-02 17:15:39 +08:00
weakref ( m_ptr , cpp_function ( [ ptr ] ( handle wr ) {
delete ptr ;
wr . dec_ref ( ) ;
} ) ) . release ( ) ;
2020-07-23 14:58:19 +08:00
return * this ;
}
template < typename Return , typename Class , typename . . . Args >
class_ & def_buffer ( Return ( Class : : * func ) ( Args . . . ) ) {
return def_buffer ( [ func ] ( type & obj ) { return ( obj . * func ) ( ) ; } ) ;
}
template < typename Return , typename Class , typename . . . Args >
class_ & def_buffer ( Return ( Class : : * func ) ( Args . . . ) const ) {
return def_buffer ( [ func ] ( const type & obj ) { return ( obj . * func ) ( ) ; } ) ;
}
template < typename C , typename D , typename . . . Extra >
class_ & def_readwrite ( const char * name , D C : : * pm , const Extra & . . . extra ) {
static_assert ( std : : is_same < C , type > : : value | | std : : is_base_of < C , type > : : value , " def_readwrite() requires a class member (or base class member) " ) ;
cpp_function fget ( [ pm ] ( const type & c ) - > const D & { return c . * pm ; } , is_method ( * this ) ) ,
fset ( [ pm ] ( type & c , const D & value ) { c . * pm = value ; } , is_method ( * this ) ) ;
def_property ( name , fget , fset , return_value_policy : : reference_internal , extra . . . ) ;
return * this ;
}
template < typename C , typename D , typename . . . Extra >
class_ & def_readonly ( const char * name , const D C : : * pm , const Extra & . . . extra ) {
static_assert ( std : : is_same < C , type > : : value | | std : : is_base_of < C , type > : : value , " def_readonly() requires a class member (or base class member) " ) ;
cpp_function fget ( [ pm ] ( const type & c ) - > const D & { return c . * pm ; } , is_method ( * this ) ) ;
def_property_readonly ( name , fget , return_value_policy : : reference_internal , extra . . . ) ;
return * this ;
}
template < typename D , typename . . . Extra >
class_ & def_readwrite_static ( const char * name , D * pm , const Extra & . . . extra ) {
cpp_function fget ( [ pm ] ( object ) - > const D & { return * pm ; } , scope ( * this ) ) ,
fset ( [ pm ] ( object , const D & value ) { * pm = value ; } , scope ( * this ) ) ;
def_property_static ( name , fget , fset , return_value_policy : : reference , extra . . . ) ;
return * this ;
}
template < typename D , typename . . . Extra >
class_ & def_readonly_static ( const char * name , const D * pm , const Extra & . . . extra ) {
cpp_function fget ( [ pm ] ( object ) - > const D & { return * pm ; } , scope ( * this ) ) ;
def_property_readonly_static ( name , fget , return_value_policy : : reference , extra . . . ) ;
return * this ;
}
/// Uses return_value_policy::reference_internal by default
template < typename Getter , typename . . . Extra >
class_ & def_property_readonly ( const char * name , const Getter & fget , const Extra & . . . extra ) {
return def_property_readonly ( name , cpp_function ( method_adaptor < type > ( fget ) ) ,
return_value_policy : : reference_internal , extra . . . ) ;
}
/// Uses cpp_function's return_value_policy by default
template < typename . . . Extra >
class_ & def_property_readonly ( const char * name , const cpp_function & fget , const Extra & . . . extra ) {
return def_property ( name , fget , nullptr , extra . . . ) ;
}
/// Uses return_value_policy::reference by default
template < typename Getter , typename . . . Extra >
class_ & def_property_readonly_static ( const char * name , const Getter & fget , const Extra & . . . extra ) {
return def_property_readonly_static ( name , cpp_function ( fget ) , return_value_policy : : reference , extra . . . ) ;
}
/// Uses cpp_function's return_value_policy by default
template < typename . . . Extra >
class_ & def_property_readonly_static ( const char * name , const cpp_function & fget , const Extra & . . . extra ) {
return def_property_static ( name , fget , nullptr , extra . . . ) ;
}
/// Uses return_value_policy::reference_internal by default
template < typename Getter , typename Setter , typename . . . Extra >
class_ & def_property ( const char * name , const Getter & fget , const Setter & fset , const Extra & . . . extra ) {
return def_property ( name , fget , cpp_function ( method_adaptor < type > ( fset ) ) , extra . . . ) ;
}
template < typename Getter , typename . . . Extra >
class_ & def_property ( const char * name , const Getter & fget , const cpp_function & fset , const Extra & . . . extra ) {
return def_property ( name , cpp_function ( method_adaptor < type > ( fget ) ) , fset ,
return_value_policy : : reference_internal , extra . . . ) ;
}
/// Uses cpp_function's return_value_policy by default
template < typename . . . Extra >
class_ & def_property ( const char * name , const cpp_function & fget , const cpp_function & fset , const Extra & . . . extra ) {
return def_property_static ( name , fget , fset , is_method ( * this ) , extra . . . ) ;
}
/// Uses return_value_policy::reference by default
template < typename Getter , typename . . . Extra >
class_ & def_property_static ( const char * name , const Getter & fget , const cpp_function & fset , const Extra & . . . extra ) {
return def_property_static ( name , cpp_function ( fget ) , fset , return_value_policy : : reference , extra . . . ) ;
}
/// Uses cpp_function's return_value_policy by default
template < typename . . . Extra >
class_ & def_property_static ( const char * name , const cpp_function & fget , const cpp_function & fset , const Extra & . . . extra ) {
static_assert ( 0 = = detail : : constexpr_sum ( std : : is_base_of < arg , Extra > : : value . . . ) ,
" Argument annotations are not allowed for properties " ) ;
auto rec_fget = get_function_record ( fget ) , rec_fset = get_function_record ( fset ) ;
auto * rec_active = rec_fget ;
if ( rec_fget ) {
char * doc_prev = rec_fget - > doc ; /* 'extra' field may include a property-specific documentation string */
detail : : process_attributes < Extra . . . > : : init ( extra . . . , rec_fget ) ;
if ( rec_fget - > doc & & rec_fget - > doc ! = doc_prev ) {
free ( doc_prev ) ;
rec_fget - > doc = strdup ( rec_fget - > doc ) ;
}
}
if ( rec_fset ) {
char * doc_prev = rec_fset - > doc ;
detail : : process_attributes < Extra . . . > : : init ( extra . . . , rec_fset ) ;
if ( rec_fset - > doc & & rec_fset - > doc ! = doc_prev ) {
free ( doc_prev ) ;
rec_fset - > doc = strdup ( rec_fset - > doc ) ;
}
if ( ! rec_active ) rec_active = rec_fset ;
}
def_property_static_impl ( name , fget , fset , rec_active ) ;
return * this ;
}
private :
/// Initialize holder object, variant 1: object derives from enable_shared_from_this
template < typename T >
static void init_holder ( detail : : instance * inst , detail : : value_and_holder & v_h ,
const holder_type * /* unused */ , const std : : enable_shared_from_this < T > * /* dummy */ ) {
try {
auto sh = std : : dynamic_pointer_cast < typename holder_type : : element_type > (
v_h . value_ptr < type > ( ) - > shared_from_this ( ) ) ;
if ( sh ) {
new ( std : : addressof ( v_h . holder < holder_type > ( ) ) ) holder_type ( std : : move ( sh ) ) ;
v_h . set_holder_constructed ( ) ;
}
} catch ( const std : : bad_weak_ptr & ) { }
if ( ! v_h . holder_constructed ( ) & & inst - > owned ) {
new ( std : : addressof ( v_h . holder < holder_type > ( ) ) ) holder_type ( v_h . value_ptr < type > ( ) ) ;
v_h . set_holder_constructed ( ) ;
}
}
static void init_holder_from_existing ( const detail : : value_and_holder & v_h ,
const holder_type * holder_ptr , std : : true_type /*is_copy_constructible*/ ) {
new ( std : : addressof ( v_h . holder < holder_type > ( ) ) ) holder_type ( * reinterpret_cast < const holder_type * > ( holder_ptr ) ) ;
}
static void init_holder_from_existing ( const detail : : value_and_holder & v_h ,
const holder_type * holder_ptr , std : : false_type /*is_copy_constructible*/ ) {
new ( std : : addressof ( v_h . holder < holder_type > ( ) ) ) holder_type ( std : : move ( * const_cast < holder_type * > ( holder_ptr ) ) ) ;
}
/// Initialize holder object, variant 2: try to construct from existing holder object, if possible
static void init_holder ( detail : : instance * inst , detail : : value_and_holder & v_h ,
const holder_type * holder_ptr , const void * /* dummy -- not enable_shared_from_this<T>) */ ) {
if ( holder_ptr ) {
init_holder_from_existing ( v_h , holder_ptr , std : : is_copy_constructible < holder_type > ( ) ) ;
v_h . set_holder_constructed ( ) ;
} else if ( inst - > owned | | detail : : always_construct_holder < holder_type > : : value ) {
new ( std : : addressof ( v_h . holder < holder_type > ( ) ) ) holder_type ( v_h . value_ptr < type > ( ) ) ;
v_h . set_holder_constructed ( ) ;
}
}
/// Performs instance initialization including constructing a holder and registering the known
/// instance. Should be called as soon as the `type` value_ptr is set for an instance. Takes an
/// optional pointer to an existing holder to use; if not specified and the instance is
/// `.owned`, a new holder will be constructed to manage the value pointer.
static void init_instance ( detail : : instance * inst , const void * holder_ptr ) {
auto v_h = inst - > get_value_and_holder ( detail : : get_type_info ( typeid ( type ) ) ) ;
if ( ! v_h . instance_registered ( ) ) {
register_instance ( inst , v_h . value_ptr ( ) , v_h . type ) ;
v_h . set_instance_registered ( ) ;
}
init_holder ( inst , v_h , ( const holder_type * ) holder_ptr , v_h . value_ptr < type > ( ) ) ;
}
/// Deallocates an instance; via holder, if constructed; otherwise via operator delete.
static void dealloc ( detail : : value_and_holder & v_h ) {
2021-01-02 17:15:39 +08:00
// We could be deallocating because we are cleaning up after a Python exception.
// If so, the Python error indicator will be set. We need to clear that before
// running the destructor, in case the destructor code calls more Python.
// If we don't, the Python API will exit with an exception, and pybind11 will
// throw error_already_set from the C++ destructor which is forbidden and triggers
// std::terminate().
error_scope scope ;
2020-07-23 14:58:19 +08:00
if ( v_h . holder_constructed ( ) ) {
v_h . holder < holder_type > ( ) . ~ holder_type ( ) ;
v_h . set_holder_constructed ( false ) ;
}
else {
detail : : call_operator_delete ( v_h . value_ptr < type > ( ) ,
v_h . type - > type_size ,
v_h . type - > type_align
) ;
}
v_h . value_ptr ( ) = nullptr ;
}
static detail : : function_record * get_function_record ( handle h ) {
h = detail : : get_function ( h ) ;
return h ? ( detail : : function_record * ) reinterpret_borrow < capsule > ( PyCFunction_GET_SELF ( h . ptr ( ) ) )
: nullptr ;
}
} ;
/// Binds an existing constructor taking arguments Args...
template < typename . . . Args > detail : : initimpl : : constructor < Args . . . > init ( ) { return { } ; }
/// Like `init<Args...>()`, but the instance is always constructed through the alias class (even
/// when not inheriting on the Python side).
template < typename . . . Args > detail : : initimpl : : alias_constructor < Args . . . > init_alias ( ) { return { } ; }
/// Binds a factory function as a constructor
template < typename Func , typename Ret = detail : : initimpl : : factory < Func > >
Ret init ( Func & & f ) { return { std : : forward < Func > ( f ) } ; }
/// Dual-argument factory function: the first function is called when no alias is needed, the second
/// when an alias is needed (i.e. due to python-side inheritance). Arguments must be identical.
template < typename CFunc , typename AFunc , typename Ret = detail : : initimpl : : factory < CFunc , AFunc > >
Ret init ( CFunc & & c , AFunc & & a ) {
return { std : : forward < CFunc > ( c ) , std : : forward < AFunc > ( a ) } ;
}
/// Binds pickling functions `__getstate__` and `__setstate__` and ensures that the type
/// returned by `__getstate__` is the same as the argument accepted by `__setstate__`.
template < typename GetState , typename SetState >
detail : : initimpl : : pickle_factory < GetState , SetState > pickle ( GetState & & g , SetState & & s ) {
return { std : : forward < GetState > ( g ) , std : : forward < SetState > ( s ) } ;
}
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_BEGIN ( detail )
inline str enum_name ( handle arg ) {
dict entries = arg . get_type ( ) . attr ( " __entries " ) ;
for ( auto kv : entries ) {
if ( handle ( kv . second [ int_ ( 0 ) ] ) . equal ( arg ) )
return pybind11 : : str ( kv . first ) ;
}
return " ??? " ;
}
2020-07-23 14:58:19 +08:00
struct enum_base {
enum_base ( handle base , handle parent ) : m_base ( base ) , m_parent ( parent ) { }
PYBIND11_NOINLINE void init ( bool is_arithmetic , bool is_convertible ) {
m_base . attr ( " __entries " ) = dict ( ) ;
auto property = handle ( ( PyObject * ) & PyProperty_Type ) ;
auto static_property = handle ( ( PyObject * ) get_internals ( ) . static_property_type ) ;
m_base . attr ( " __repr__ " ) = cpp_function (
2021-01-02 17:15:39 +08:00
[ ] ( object arg ) - > str {
handle type = type : : handle_of ( arg ) ;
2020-07-23 14:58:19 +08:00
object type_name = type . attr ( " __name__ " ) ;
2021-01-02 17:15:39 +08:00
return pybind11 : : str ( " <{}.{}: {}> " ) . format ( type_name , enum_name ( arg ) , int_ ( arg ) ) ;
} , name ( " __repr__ " ) , is_method ( m_base )
2020-07-23 14:58:19 +08:00
) ;
2021-01-02 17:15:39 +08:00
m_base . attr ( " name " ) = property ( cpp_function ( & enum_name , name ( " name " ) , is_method ( m_base ) ) ) ;
m_base . attr ( " __str__ " ) = cpp_function (
2020-07-23 14:58:19 +08:00
[ ] ( handle arg ) - > str {
2021-01-02 17:15:39 +08:00
object type_name = type : : handle_of ( arg ) . attr ( " __name__ " ) ;
return pybind11 : : str ( " {}.{} " ) . format ( type_name , enum_name ( arg ) ) ;
} , name ( " name " ) , is_method ( m_base )
) ;
2020-07-23 14:58:19 +08:00
m_base . attr ( " __doc__ " ) = static_property ( cpp_function (
[ ] ( handle arg ) - > std : : string {
std : : string docstring ;
dict entries = arg . attr ( " __entries " ) ;
if ( ( ( PyTypeObject * ) arg . ptr ( ) ) - > tp_doc )
docstring + = std : : string ( ( ( PyTypeObject * ) arg . ptr ( ) ) - > tp_doc ) + " \n \n " ;
docstring + = " Members: " ;
2021-01-02 17:15:39 +08:00
for ( auto kv : entries ) {
2020-07-23 14:58:19 +08:00
auto key = std : : string ( pybind11 : : str ( kv . first ) ) ;
auto comment = kv . second [ int_ ( 1 ) ] ;
docstring + = " \n \n " + key ;
if ( ! comment . is_none ( ) )
docstring + = " : " + ( std : : string ) pybind11 : : str ( comment ) ;
}
return docstring ;
2021-01-02 17:15:39 +08:00
} , name ( " __doc__ " )
2020-07-23 14:58:19 +08:00
) , none ( ) , none ( ) , " " ) ;
m_base . attr ( " __members__ " ) = static_property ( cpp_function (
[ ] ( handle arg ) - > dict {
dict entries = arg . attr ( " __entries " ) , m ;
2021-01-02 17:15:39 +08:00
for ( auto kv : entries )
2020-07-23 14:58:19 +08:00
m [ kv . first ] = kv . second [ int_ ( 0 ) ] ;
return m ;
2021-01-02 17:15:39 +08:00
} , name ( " __members__ " ) ) , none ( ) , none ( ) , " "
2020-07-23 14:58:19 +08:00
) ;
# define PYBIND11_ENUM_OP_STRICT(op, expr, strict_behavior) \
m_base . attr ( op ) = cpp_function ( \
[ ] ( object a , object b ) { \
2021-01-02 17:15:39 +08:00
if ( ! type : : handle_of ( a ) . is ( type : : handle_of ( b ) ) ) \
2020-07-23 14:58:19 +08:00
strict_behavior ; \
return expr ; \
} , \
2021-01-02 17:15:39 +08:00
name ( op ) , is_method ( m_base ) , arg ( " other " ) )
2020-07-23 14:58:19 +08:00
# define PYBIND11_ENUM_OP_CONV(op, expr) \
m_base . attr ( op ) = cpp_function ( \
[ ] ( object a_ , object b_ ) { \
int_ a ( a_ ) , b ( b_ ) ; \
return expr ; \
} , \
2021-01-02 17:15:39 +08:00
name ( op ) , is_method ( m_base ) , arg ( " other " ) )
2020-07-23 14:58:19 +08:00
# define PYBIND11_ENUM_OP_CONV_LHS(op, expr) \
m_base . attr ( op ) = cpp_function ( \
[ ] ( object a_ , object b ) { \
int_ a ( a_ ) ; \
return expr ; \
} , \
2021-01-02 17:15:39 +08:00
name ( op ) , is_method ( m_base ) , arg ( " other " ) )
2020-07-23 14:58:19 +08:00
if ( is_convertible ) {
PYBIND11_ENUM_OP_CONV_LHS ( " __eq__ " , ! b . is_none ( ) & & a . equal ( b ) ) ;
PYBIND11_ENUM_OP_CONV_LHS ( " __ne__ " , b . is_none ( ) | | ! a . equal ( b ) ) ;
if ( is_arithmetic ) {
PYBIND11_ENUM_OP_CONV ( " __lt__ " , a < b ) ;
PYBIND11_ENUM_OP_CONV ( " __gt__ " , a > b ) ;
PYBIND11_ENUM_OP_CONV ( " __le__ " , a < = b ) ;
PYBIND11_ENUM_OP_CONV ( " __ge__ " , a > = b ) ;
PYBIND11_ENUM_OP_CONV ( " __and__ " , a & b ) ;
PYBIND11_ENUM_OP_CONV ( " __rand__ " , a & b ) ;
PYBIND11_ENUM_OP_CONV ( " __or__ " , a | b ) ;
PYBIND11_ENUM_OP_CONV ( " __ror__ " , a | b ) ;
PYBIND11_ENUM_OP_CONV ( " __xor__ " , a ^ b ) ;
PYBIND11_ENUM_OP_CONV ( " __rxor__ " , a ^ b ) ;
m_base . attr ( " __invert__ " ) = cpp_function (
2021-01-02 17:15:39 +08:00
[ ] ( object arg ) { return ~ ( int_ ( arg ) ) ; } , name ( " __invert__ " ) , is_method ( m_base ) ) ;
2020-07-23 14:58:19 +08:00
}
} else {
PYBIND11_ENUM_OP_STRICT ( " __eq__ " , int_ ( a ) . equal ( int_ ( b ) ) , return false ) ;
PYBIND11_ENUM_OP_STRICT ( " __ne__ " , ! int_ ( a ) . equal ( int_ ( b ) ) , return true ) ;
if ( is_arithmetic ) {
# define PYBIND11_THROW throw type_error("Expected an enumeration of matching type!");
PYBIND11_ENUM_OP_STRICT ( " __lt__ " , int_ ( a ) < int_ ( b ) , PYBIND11_THROW ) ;
PYBIND11_ENUM_OP_STRICT ( " __gt__ " , int_ ( a ) > int_ ( b ) , PYBIND11_THROW ) ;
PYBIND11_ENUM_OP_STRICT ( " __le__ " , int_ ( a ) < = int_ ( b ) , PYBIND11_THROW ) ;
PYBIND11_ENUM_OP_STRICT ( " __ge__ " , int_ ( a ) > = int_ ( b ) , PYBIND11_THROW ) ;
# undef PYBIND11_THROW
}
}
# undef PYBIND11_ENUM_OP_CONV_LHS
# undef PYBIND11_ENUM_OP_CONV
# undef PYBIND11_ENUM_OP_STRICT
2021-01-02 17:15:39 +08:00
m_base . attr ( " __getstate__ " ) = cpp_function (
[ ] ( object arg ) { return int_ ( arg ) ; } , name ( " __getstate__ " ) , is_method ( m_base ) ) ;
2020-07-23 14:58:19 +08:00
2021-01-02 17:15:39 +08:00
m_base . attr ( " __hash__ " ) = cpp_function (
[ ] ( object arg ) { return int_ ( arg ) ; } , name ( " __hash__ " ) , is_method ( m_base ) ) ;
2020-07-23 14:58:19 +08:00
}
PYBIND11_NOINLINE void value ( char const * name_ , object value , const char * doc = nullptr ) {
dict entries = m_base . attr ( " __entries " ) ;
str name ( name_ ) ;
if ( entries . contains ( name ) ) {
std : : string type_name = ( std : : string ) str ( m_base . attr ( " __name__ " ) ) ;
throw value_error ( type_name + " : element \" " + std : : string ( name_ ) + " \" already exists! " ) ;
}
entries [ name ] = std : : make_pair ( value , doc ) ;
m_base . attr ( name ) = value ;
}
PYBIND11_NOINLINE void export_values ( ) {
dict entries = m_base . attr ( " __entries " ) ;
2021-01-02 17:15:39 +08:00
for ( auto kv : entries )
2020-07-23 14:58:19 +08:00
m_parent . attr ( kv . first ) = kv . second [ int_ ( 0 ) ] ;
}
handle m_base ;
handle m_parent ;
} ;
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_END ( detail )
2020-07-23 14:58:19 +08:00
/// Binds C++ enumerations and enumeration classes to Python
template < typename Type > class enum_ : public class_ < Type > {
public :
using Base = class_ < Type > ;
using Base : : def ;
using Base : : attr ;
using Base : : def_property_readonly ;
using Base : : def_property_readonly_static ;
using Scalar = typename std : : underlying_type < Type > : : type ;
template < typename . . . Extra >
enum_ ( const handle & scope , const char * name , const Extra & . . . extra )
: class_ < Type > ( scope , name , extra . . . ) , m_base ( * this , scope ) {
constexpr bool is_arithmetic = detail : : any_of < std : : is_same < arithmetic , Extra > . . . > : : value ;
constexpr bool is_convertible = std : : is_convertible < Type , Scalar > : : value ;
m_base . init ( is_arithmetic , is_convertible ) ;
2021-01-02 17:15:39 +08:00
def ( init ( [ ] ( Scalar i ) { return static_cast < Type > ( i ) ; } ) , arg ( " value " ) ) ;
2020-07-23 14:58:19 +08:00
def ( " __int__ " , [ ] ( Type value ) { return ( Scalar ) value ; } ) ;
# if PY_MAJOR_VERSION < 3
def ( " __long__ " , [ ] ( Type value ) { return ( Scalar ) value ; } ) ;
# endif
# if PY_MAJOR_VERSION > 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 8)
def ( " __index__ " , [ ] ( Type value ) { return ( Scalar ) value ; } ) ;
# endif
2021-01-02 17:15:39 +08:00
attr ( " __setstate__ " ) = cpp_function (
[ ] ( detail : : value_and_holder & v_h , Scalar arg ) {
detail : : initimpl : : setstate < Base > ( v_h , static_cast < Type > ( arg ) ,
Py_TYPE ( v_h . inst ) ! = v_h . type - > type ) ; } ,
detail : : is_new_style_constructor ( ) ,
pybind11 : : name ( " __setstate__ " ) , is_method ( * this ) , arg ( " state " ) ) ;
2020-07-23 14:58:19 +08:00
}
/// Export enumeration entries into the parent scope
enum_ & export_values ( ) {
m_base . export_values ( ) ;
return * this ;
}
/// Add an enumeration entry
enum_ & value ( char const * name , Type value , const char * doc = nullptr ) {
m_base . value ( name , pybind11 : : cast ( value , return_value_policy : : copy ) , doc ) ;
return * this ;
}
private :
detail : : enum_base m_base ;
} ;
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_BEGIN ( detail )
2020-07-23 14:58:19 +08:00
inline void keep_alive_impl ( handle nurse , handle patient ) {
if ( ! nurse | | ! patient )
pybind11_fail ( " Could not activate keep_alive! " ) ;
if ( patient . is_none ( ) | | nurse . is_none ( ) )
return ; /* Nothing to keep alive or nothing to be kept alive by */
auto tinfo = all_type_info ( Py_TYPE ( nurse . ptr ( ) ) ) ;
if ( ! tinfo . empty ( ) ) {
/* It's a pybind-registered type, so we can store the patient in the
* internal list . */
add_patient ( nurse . ptr ( ) , patient . ptr ( ) ) ;
}
else {
/* Fall back to clever approach based on weak references taken from
* Boost . Python . This is not used for pybind - registered types because
* the objects can be destroyed out - of - order in a GC pass . */
cpp_function disable_lifesupport (
[ patient ] ( handle weakref ) { patient . dec_ref ( ) ; weakref . dec_ref ( ) ; } ) ;
weakref wr ( nurse , disable_lifesupport ) ;
patient . inc_ref ( ) ; /* reference patient and leak the weak reference */
( void ) wr . release ( ) ;
}
}
PYBIND11_NOINLINE inline void keep_alive_impl ( size_t Nurse , size_t Patient , function_call & call , handle ret ) {
auto get_arg = [ & ] ( size_t n ) {
if ( n = = 0 )
return ret ;
else if ( n = = 1 & & call . init_self )
return call . init_self ;
else if ( n < = call . args . size ( ) )
return call . args [ n - 1 ] ;
return handle ( ) ;
} ;
keep_alive_impl ( get_arg ( Nurse ) , get_arg ( Patient ) ) ;
}
inline std : : pair < decltype ( internals : : registered_types_py ) : : iterator , bool > all_type_info_get_cache ( PyTypeObject * type ) {
auto res = get_internals ( ) . registered_types_py
# ifdef __cpp_lib_unordered_map_try_emplace
. try_emplace ( type ) ;
# else
. emplace ( type , std : : vector < detail : : type_info * > ( ) ) ;
# endif
if ( res . second ) {
// New cache entry created; set up a weak reference to automatically remove it if the type
// gets destroyed:
weakref ( ( PyObject * ) type , cpp_function ( [ type ] ( handle wr ) {
get_internals ( ) . registered_types_py . erase ( type ) ;
wr . dec_ref ( ) ;
} ) ) . release ( ) ;
}
return res ;
}
template < typename Iterator , typename Sentinel , bool KeyIterator , return_value_policy Policy >
struct iterator_state {
Iterator it ;
Sentinel end ;
bool first_or_done ;
} ;
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_END ( detail )
2020-07-23 14:58:19 +08:00
/// Makes a python iterator from a first and past-the-end C++ InputIterator.
template < return_value_policy Policy = return_value_policy : : reference_internal ,
typename Iterator ,
typename Sentinel ,
typename ValueType = decltype ( * std : : declval < Iterator > ( ) ) ,
typename . . . Extra >
iterator make_iterator ( Iterator first , Sentinel last , Extra & & . . . extra ) {
2021-01-02 17:15:39 +08:00
using state = detail : : iterator_state < Iterator , Sentinel , false , Policy > ;
2020-07-23 14:58:19 +08:00
if ( ! detail : : get_type_info ( typeid ( state ) , false ) ) {
class_ < state > ( handle ( ) , " iterator " , pybind11 : : module_local ( ) )
. def ( " __iter__ " , [ ] ( state & s ) - > state & { return s ; } )
. def ( " __next__ " , [ ] ( state & s ) - > ValueType {
if ( ! s . first_or_done )
+ + s . it ;
else
s . first_or_done = false ;
if ( s . it = = s . end ) {
s . first_or_done = true ;
throw stop_iteration ( ) ;
}
return * s . it ;
} , std : : forward < Extra > ( extra ) . . . , Policy ) ;
}
return cast ( state { first , last , true } ) ;
}
/// Makes an python iterator over the keys (`.first`) of a iterator over pairs from a
/// first and past-the-end InputIterator.
template < return_value_policy Policy = return_value_policy : : reference_internal ,
typename Iterator ,
typename Sentinel ,
typename KeyType = decltype ( ( * std : : declval < Iterator > ( ) ) . first ) ,
typename . . . Extra >
iterator make_key_iterator ( Iterator first , Sentinel last , Extra & & . . . extra ) {
2021-01-02 17:15:39 +08:00
using state = detail : : iterator_state < Iterator , Sentinel , true , Policy > ;
2020-07-23 14:58:19 +08:00
if ( ! detail : : get_type_info ( typeid ( state ) , false ) ) {
class_ < state > ( handle ( ) , " iterator " , pybind11 : : module_local ( ) )
. def ( " __iter__ " , [ ] ( state & s ) - > state & { return s ; } )
. def ( " __next__ " , [ ] ( state & s ) - > KeyType {
if ( ! s . first_or_done )
+ + s . it ;
else
s . first_or_done = false ;
if ( s . it = = s . end ) {
s . first_or_done = true ;
throw stop_iteration ( ) ;
}
return ( * s . it ) . first ;
} , std : : forward < Extra > ( extra ) . . . , Policy ) ;
}
return cast ( state { first , last , true } ) ;
}
/// Makes an iterator over values of an stl container or other container supporting
/// `std::begin()`/`std::end()`
template < return_value_policy Policy = return_value_policy : : reference_internal ,
typename Type , typename . . . Extra > iterator make_iterator ( Type & value , Extra & & . . . extra ) {
return make_iterator < Policy > ( std : : begin ( value ) , std : : end ( value ) , extra . . . ) ;
}
/// Makes an iterator over the keys (`.first`) of a stl map-like container supporting
/// `std::begin()`/`std::end()`
template < return_value_policy Policy = return_value_policy : : reference_internal ,
typename Type , typename . . . Extra > iterator make_key_iterator ( Type & value , Extra & & . . . extra ) {
return make_key_iterator < Policy > ( std : : begin ( value ) , std : : end ( value ) , extra . . . ) ;
}
template < typename InputType , typename OutputType > void implicitly_convertible ( ) {
struct set_flag {
bool & flag ;
set_flag ( bool & flag ) : flag ( flag ) { flag = true ; }
~ set_flag ( ) { flag = false ; }
} ;
auto implicit_caster = [ ] ( PyObject * obj , PyTypeObject * type ) - > PyObject * {
static bool currently_used = false ;
if ( currently_used ) // implicit conversions are non-reentrant
return nullptr ;
set_flag flag_helper ( currently_used ) ;
if ( ! detail : : make_caster < InputType > ( ) . load ( obj , false ) )
return nullptr ;
tuple args ( 1 ) ;
args [ 0 ] = obj ;
PyObject * result = PyObject_Call ( ( PyObject * ) type , args . ptr ( ) , nullptr ) ;
if ( result = = nullptr )
PyErr_Clear ( ) ;
return result ;
} ;
if ( auto tinfo = detail : : get_type_info ( typeid ( OutputType ) ) )
tinfo - > implicit_conversions . push_back ( implicit_caster ) ;
else
pybind11_fail ( " implicitly_convertible: Unable to find type " + type_id < OutputType > ( ) ) ;
}
template < typename ExceptionTranslator >
void register_exception_translator ( ExceptionTranslator & & translator ) {
detail : : get_internals ( ) . registered_exception_translators . push_front (
std : : forward < ExceptionTranslator > ( translator ) ) ;
}
/**
* Wrapper to generate a new Python exception type .
*
* This should only be used with PyErr_SetString for now .
* It is not ( yet ) possible to use as a py : : base .
* Template type argument is reserved for future use .
*/
template < typename type >
class exception : public object {
public :
exception ( ) = default ;
2021-01-02 17:15:39 +08:00
exception ( handle scope , const char * name , handle base = PyExc_Exception ) {
2020-07-23 14:58:19 +08:00
std : : string full_name = scope . attr ( " __name__ " ) . cast < std : : string > ( ) +
std : : string ( " . " ) + name ;
2021-01-02 17:15:39 +08:00
m_ptr = PyErr_NewException ( const_cast < char * > ( full_name . c_str ( ) ) , base . ptr ( ) , NULL ) ;
if ( hasattr ( scope , " __dict__ " ) & & scope . attr ( " __dict__ " ) . contains ( name ) )
2020-07-23 14:58:19 +08:00
pybind11_fail ( " Error during initialization: multiple incompatible "
" definitions with name \" " + std : : string ( name ) + " \" " ) ;
scope . attr ( name ) = * this ;
}
// Sets the current python exception to this exception object with the given message
void operator ( ) ( const char * message ) {
PyErr_SetString ( m_ptr , message ) ;
}
} ;
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_BEGIN ( detail )
2020-07-23 14:58:19 +08:00
// Returns a reference to a function-local static exception object used in the simple
// register_exception approach below. (It would be simpler to have the static local variable
// directly in register_exception, but that makes clang <3.5 segfault - issue #1349).
template < typename CppException >
exception < CppException > & get_exception_object ( ) { static exception < CppException > ex ; return ex ; }
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_END ( detail )
2020-07-23 14:58:19 +08:00
/**
* Registers a Python exception in ` m ` of the given ` name ` and installs an exception translator to
* translate the C + + exception to the created Python exception using the exceptions what ( ) method .
* This is intended for simple exception translations ; for more complex translation , register the
* exception object and translator directly .
*/
template < typename CppException >
exception < CppException > & register_exception ( handle scope ,
const char * name ,
2021-01-02 17:15:39 +08:00
handle base = PyExc_Exception ) {
2020-07-23 14:58:19 +08:00
auto & ex = detail : : get_exception_object < CppException > ( ) ;
if ( ! ex ) ex = exception < CppException > ( scope , name , base ) ;
register_exception_translator ( [ ] ( std : : exception_ptr p ) {
if ( ! p ) return ;
try {
std : : rethrow_exception ( p ) ;
} catch ( const CppException & e ) {
detail : : get_exception_object < CppException > ( ) ( e . what ( ) ) ;
}
} ) ;
return ex ;
}
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_BEGIN ( detail )
2020-07-23 14:58:19 +08:00
PYBIND11_NOINLINE inline void print ( tuple args , dict kwargs ) {
auto strings = tuple ( args . size ( ) ) ;
for ( size_t i = 0 ; i < args . size ( ) ; + + i ) {
strings [ i ] = str ( args [ i ] ) ;
}
auto sep = kwargs . contains ( " sep " ) ? kwargs [ " sep " ] : cast ( " " ) ;
auto line = sep . attr ( " join " ) ( strings ) ;
object file ;
if ( kwargs . contains ( " file " ) ) {
file = kwargs [ " file " ] . cast < object > ( ) ;
} else {
try {
2021-01-02 17:15:39 +08:00
file = module_ : : import ( " sys " ) . attr ( " stdout " ) ;
2020-07-23 14:58:19 +08:00
} catch ( const error_already_set & ) {
/* If print() is called from code that is executed as
part of garbage collection during interpreter shutdown ,
importing ' sys ' can fail . Give up rather than crashing the
interpreter in this case . */
return ;
}
}
auto write = file . attr ( " write " ) ;
write ( line ) ;
write ( kwargs . contains ( " end " ) ? kwargs [ " end " ] : cast ( " \n " ) ) ;
if ( kwargs . contains ( " flush " ) & & kwargs [ " flush " ] . cast < bool > ( ) )
file . attr ( " flush " ) ( ) ;
}
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_END ( detail )
2020-07-23 14:58:19 +08:00
template < return_value_policy policy = return_value_policy : : automatic_reference , typename . . . Args >
void print ( Args & & . . . args ) {
auto c = detail : : collect_arguments < policy > ( std : : forward < Args > ( args ) . . . ) ;
detail : : print ( c . args ( ) , c . kwargs ( ) ) ;
}
# if defined(WITH_THREAD) && !defined(PYPY_VERSION)
/* The functions below essentially reproduce the PyGILState_* API using a RAII
* pattern , but there are a few important differences :
*
* 1. When acquiring the GIL from an non - main thread during the finalization
* phase , the GILState API blindly terminates the calling thread , which
* is often not what is wanted . This API does not do this .
*
* 2. The gil_scoped_release function can optionally cut the relationship
* of a PyThreadState and its associated thread , which allows moving it to
* another thread ( this is a fairly rare / advanced use case ) .
*
* 3. The reference count of an acquired thread state can be controlled . This
* can be handy to prevent cases where callbacks issued from an external
* thread would otherwise constantly construct and destroy thread state data
* structures .
*
* See the Python bindings of NanoGUI ( http : //github.com/wjakob/nanogui) for an
* example which uses features 2 and 3 to migrate the Python thread of
* execution to another thread ( to run the event loop on the original thread ,
* in this case ) .
*/
class gil_scoped_acquire {
public :
PYBIND11_NOINLINE gil_scoped_acquire ( ) {
auto const & internals = detail : : get_internals ( ) ;
tstate = ( PyThreadState * ) PYBIND11_TLS_GET_VALUE ( internals . tstate ) ;
if ( ! tstate ) {
/* Check if the GIL was acquired using the PyGILState_* API instead (e.g. if
calling from a Python thread ) . Since we use a different key , this ensures
we don ' t create a new thread state and deadlock in PyEval_AcquireThread
below . Note we don ' t save this state with internals . tstate , since we don ' t
create it we would fail to clear it ( its reference count should be > 0 ) . */
tstate = PyGILState_GetThisThreadState ( ) ;
}
if ( ! tstate ) {
tstate = PyThreadState_New ( internals . istate ) ;
# if !defined(NDEBUG)
if ( ! tstate )
pybind11_fail ( " scoped_acquire: could not create thread state! " ) ;
# endif
tstate - > gilstate_counter = 0 ;
PYBIND11_TLS_REPLACE_VALUE ( internals . tstate , tstate ) ;
} else {
release = detail : : get_thread_state_unchecked ( ) ! = tstate ;
}
if ( release ) {
/* Work around an annoying assertion in PyThreadState_Swap */
# if defined(Py_DEBUG)
PyInterpreterState * interp = tstate - > interp ;
tstate - > interp = nullptr ;
# endif
PyEval_AcquireThread ( tstate ) ;
# if defined(Py_DEBUG)
tstate - > interp = interp ;
# endif
}
inc_ref ( ) ;
}
void inc_ref ( ) {
+ + tstate - > gilstate_counter ;
}
PYBIND11_NOINLINE void dec_ref ( ) {
- - tstate - > gilstate_counter ;
# if !defined(NDEBUG)
if ( detail : : get_thread_state_unchecked ( ) ! = tstate )
pybind11_fail ( " scoped_acquire::dec_ref(): thread state must be current! " ) ;
if ( tstate - > gilstate_counter < 0 )
pybind11_fail ( " scoped_acquire::dec_ref(): reference count underflow! " ) ;
# endif
if ( tstate - > gilstate_counter = = 0 ) {
# if !defined(NDEBUG)
if ( ! release )
pybind11_fail ( " scoped_acquire::dec_ref(): internal error! " ) ;
# endif
PyThreadState_Clear ( tstate ) ;
PyThreadState_DeleteCurrent ( ) ;
PYBIND11_TLS_DELETE_VALUE ( detail : : get_internals ( ) . tstate ) ;
release = false ;
}
}
PYBIND11_NOINLINE ~ gil_scoped_acquire ( ) {
dec_ref ( ) ;
if ( release )
PyEval_SaveThread ( ) ;
}
private :
PyThreadState * tstate = nullptr ;
bool release = true ;
} ;
class gil_scoped_release {
public :
explicit gil_scoped_release ( bool disassoc = false ) : disassoc ( disassoc ) {
// `get_internals()` must be called here unconditionally in order to initialize
// `internals.tstate` for subsequent `gil_scoped_acquire` calls. Otherwise, an
// initialization race could occur as multiple threads try `gil_scoped_acquire`.
const auto & internals = detail : : get_internals ( ) ;
tstate = PyEval_SaveThread ( ) ;
if ( disassoc ) {
auto key = internals . tstate ;
PYBIND11_TLS_DELETE_VALUE ( key ) ;
}
}
~ gil_scoped_release ( ) {
if ( ! tstate )
return ;
PyEval_RestoreThread ( tstate ) ;
if ( disassoc ) {
auto key = detail : : get_internals ( ) . tstate ;
PYBIND11_TLS_REPLACE_VALUE ( key , tstate ) ;
}
}
private :
PyThreadState * tstate ;
bool disassoc ;
} ;
# elif defined(PYPY_VERSION)
class gil_scoped_acquire {
PyGILState_STATE state ;
public :
gil_scoped_acquire ( ) { state = PyGILState_Ensure ( ) ; }
~ gil_scoped_acquire ( ) { PyGILState_Release ( state ) ; }
} ;
class gil_scoped_release {
PyThreadState * state ;
public :
gil_scoped_release ( ) { state = PyEval_SaveThread ( ) ; }
~ gil_scoped_release ( ) { PyEval_RestoreThread ( state ) ; }
} ;
# else
class gil_scoped_acquire { } ;
class gil_scoped_release { } ;
# endif
error_already_set : : ~ error_already_set ( ) {
if ( m_type ) {
gil_scoped_acquire gil ;
error_scope scope ;
m_type . release ( ) . dec_ref ( ) ;
m_value . release ( ) . dec_ref ( ) ;
m_trace . release ( ) . dec_ref ( ) ;
}
}
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_BEGIN ( detail )
inline function get_type_override ( const void * this_ptr , const type_info * this_type , const char * name ) {
handle self = get_object_handle ( this_ptr , this_type ) ;
2020-07-23 14:58:19 +08:00
if ( ! self )
return function ( ) ;
2021-01-02 17:15:39 +08:00
handle type = type : : handle_of ( self ) ;
2020-07-23 14:58:19 +08:00
auto key = std : : make_pair ( type . ptr ( ) , name ) ;
2021-01-02 17:15:39 +08:00
/* Cache functions that aren't overridden in Python to avoid
2020-07-23 14:58:19 +08:00
many costly Python dictionary lookups below */
2021-01-02 17:15:39 +08:00
auto & cache = get_internals ( ) . inactive_override_cache ;
2020-07-23 14:58:19 +08:00
if ( cache . find ( key ) ! = cache . end ( ) )
return function ( ) ;
2021-01-02 17:15:39 +08:00
function override = getattr ( self , name , function ( ) ) ;
if ( override . is_cpp_function ( ) ) {
2020-07-23 14:58:19 +08:00
cache . insert ( key ) ;
return function ( ) ;
}
/* Don't call dispatch code if invoked from overridden function.
Unfortunately this doesn ' t work on PyPy . */
# if !defined(PYPY_VERSION)
PyFrameObject * frame = PyThreadState_Get ( ) - > frame ;
if ( frame & & ( std : : string ) str ( frame - > f_code - > co_name ) = = name & &
frame - > f_code - > co_argcount > 0 ) {
PyFrame_FastToLocals ( frame ) ;
PyObject * self_caller = PyDict_GetItem (
frame - > f_locals , PyTuple_GET_ITEM ( frame - > f_code - > co_varnames , 0 ) ) ;
if ( self_caller = = self . ptr ( ) )
return function ( ) ;
}
# else
/* PyPy currently doesn't provide a detailed cpyext emulation of
frame objects , so we have to emulate this using Python . This
is going to be slow . . */
dict d ; d [ " self " ] = self ; d [ " name " ] = pybind11 : : str ( name ) ;
PyObject * result = PyRun_String (
" import inspect \n "
" frame = inspect.currentframe() \n "
" if frame is not None: \n "
" frame = frame.f_back \n "
" if frame is not None and str(frame.f_code.co_name) == name and "
" frame.f_code.co_argcount > 0: \n "
" self_caller = frame.f_locals[frame.f_code.co_varnames[0]] \n "
" if self_caller == self: \n "
" self = None \n " ,
Py_file_input , d . ptr ( ) , d . ptr ( ) ) ;
if ( result = = nullptr )
throw error_already_set ( ) ;
if ( d [ " self " ] . is_none ( ) )
return function ( ) ;
Py_DECREF ( result ) ;
# endif
2021-01-02 17:15:39 +08:00
return override ;
2020-07-23 14:58:19 +08:00
}
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_END ( detail )
2020-07-23 14:58:19 +08:00
/** \rst
Try to retrieve a python method by the provided name from the instance pointed to by the this_ptr .
2021-01-02 17:15:39 +08:00
: this_ptr : The pointer to the object the overriden method should be retrieved for . This should be
the first non - trampoline class encountered in the inheritance chain .
: name : The name of the overridden Python method to retrieve .
2020-07-23 14:58:19 +08:00
: return : The Python method by this name from the object or an empty function wrapper .
\ endrst */
2021-01-02 17:15:39 +08:00
template < class T > function get_override ( const T * this_ptr , const char * name ) {
2020-07-23 14:58:19 +08:00
auto tinfo = detail : : get_type_info ( typeid ( T ) ) ;
2021-01-02 17:15:39 +08:00
return tinfo ? detail : : get_type_override ( this_ptr , tinfo , name ) : function ( ) ;
2020-07-23 14:58:19 +08:00
}
2021-01-02 17:15:39 +08:00
# define PYBIND11_OVERRIDE_IMPL(ret_type, cname, name, ...) \
do { \
2020-07-23 14:58:19 +08:00
pybind11 : : gil_scoped_acquire gil ; \
2021-01-02 17:15:39 +08:00
pybind11 : : function override = pybind11 : : get_override ( static_cast < const cname * > ( this ) , name ) ; \
if ( override ) { \
auto o = override ( __VA_ARGS__ ) ; \
2020-07-23 14:58:19 +08:00
if ( pybind11 : : detail : : cast_is_temporary_value_reference < ret_type > : : value ) { \
2021-01-02 17:15:39 +08:00
static pybind11 : : detail : : override_caster_t < ret_type > caster ; \
2020-07-23 14:58:19 +08:00
return pybind11 : : detail : : cast_ref < ret_type > ( std : : move ( o ) , caster ) ; \
} \
else return pybind11 : : detail : : cast_safe < ret_type > ( std : : move ( o ) ) ; \
} \
2021-01-02 17:15:39 +08:00
} while ( false )
2020-07-23 14:58:19 +08:00
/** \rst
Macro to populate the virtual method in the trampoline class . This macro tries to look up a method named ' fn '
from the Python side , deals with the : ref : ` gil ` and necessary argument conversions to call this method and return
the appropriate type . See : ref : ` overriding_virtuals ` for more information . This macro should be used when the method
name in C is not the same as the method name in Python . For example with ` __str__ ` .
. . code - block : : cpp
std : : string toString ( ) override {
2021-01-02 17:15:39 +08:00
PYBIND11_OVERRIDE_NAME (
2020-07-23 14:58:19 +08:00
std : : string , // Return type (ret_type)
Animal , // Parent class (cname)
2021-01-02 17:15:39 +08:00
" __str__ " , // Name of method in Python (name)
toString , // Name of function in C++ (fn)
2020-07-23 14:58:19 +08:00
) ;
}
\ endrst */
2021-01-02 17:15:39 +08:00
# define PYBIND11_OVERRIDE_NAME(ret_type, cname, name, fn, ...) \
do { \
PYBIND11_OVERRIDE_IMPL ( PYBIND11_TYPE ( ret_type ) , PYBIND11_TYPE ( cname ) , name , __VA_ARGS__ ) ; \
return cname : : fn ( __VA_ARGS__ ) ; \
} while ( false )
2020-07-23 14:58:19 +08:00
/** \rst
2021-01-02 17:15:39 +08:00
Macro for pure virtual functions , this function is identical to : c : macro : ` PYBIND11_OVERRIDE_NAME ` , except that it
throws if no override can be found .
2020-07-23 14:58:19 +08:00
\ endrst */
2021-01-02 17:15:39 +08:00
# define PYBIND11_OVERRIDE_PURE_NAME(ret_type, cname, name, fn, ...) \
do { \
PYBIND11_OVERRIDE_IMPL ( PYBIND11_TYPE ( ret_type ) , PYBIND11_TYPE ( cname ) , name , __VA_ARGS__ ) ; \
pybind11 : : pybind11_fail ( " Tried to call pure virtual function \" " PYBIND11_STRINGIFY ( cname ) " :: " name " \" " ) ; \
} while ( false )
2020-07-23 14:58:19 +08:00
/** \rst
Macro to populate the virtual method in the trampoline class . This macro tries to look up the method
from the Python side , deals with the : ref : ` gil ` and necessary argument conversions to call this method and return
the appropriate type . This macro should be used if the method name in C and in Python are identical .
See : ref : ` overriding_virtuals ` for more information .
. . code - block : : cpp
class PyAnimal : public Animal {
public :
// Inherit the constructors
using Animal : : Animal ;
// Trampoline (need one for each virtual function)
std : : string go ( int n_times ) override {
2021-01-02 17:15:39 +08:00
PYBIND11_OVERRIDE_PURE (
2020-07-23 14:58:19 +08:00
std : : string , // Return type (ret_type)
Animal , // Parent class (cname)
go , // Name of function in C++ (must match Python name) (fn)
n_times // Argument(s) (...)
) ;
}
} ;
\ endrst */
2021-01-02 17:15:39 +08:00
# define PYBIND11_OVERRIDE(ret_type, cname, fn, ...) \
PYBIND11_OVERRIDE_NAME ( PYBIND11_TYPE ( ret_type ) , PYBIND11_TYPE ( cname ) , # fn , fn , __VA_ARGS__ )
2020-07-23 14:58:19 +08:00
/** \rst
2021-01-02 17:15:39 +08:00
Macro for pure virtual functions , this function is identical to : c : macro : ` PYBIND11_OVERRIDE ` , except that it throws
if no override can be found .
2020-07-23 14:58:19 +08:00
\ endrst */
2021-01-02 17:15:39 +08:00
# define PYBIND11_OVERRIDE_PURE(ret_type, cname, fn, ...) \
PYBIND11_OVERRIDE_PURE_NAME ( PYBIND11_TYPE ( ret_type ) , PYBIND11_TYPE ( cname ) , # fn , fn , __VA_ARGS__ )
// Deprecated versions
PYBIND11_DEPRECATED ( " get_type_overload has been deprecated " )
inline function get_type_overload ( const void * this_ptr , const detail : : type_info * this_type , const char * name ) {
return detail : : get_type_override ( this_ptr , this_type , name ) ;
}
template < class T >
inline function get_overload ( const T * this_ptr , const char * name ) {
return get_override ( this_ptr , name ) ;
}
# define PYBIND11_OVERLOAD_INT(ret_type, cname, name, ...) \
PYBIND11_OVERRIDE_IMPL ( PYBIND11_TYPE ( ret_type ) , PYBIND11_TYPE ( cname ) , name , __VA_ARGS__ )
# define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERRIDE_NAME ( PYBIND11_TYPE ( ret_type ) , PYBIND11_TYPE ( cname ) , name , fn , __VA_ARGS__ )
# define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERRIDE_PURE_NAME ( PYBIND11_TYPE ( ret_type ) , PYBIND11_TYPE ( cname ) , name , fn , __VA_ARGS__ ) ;
# define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \
PYBIND11_OVERRIDE ( PYBIND11_TYPE ( ret_type ) , PYBIND11_TYPE ( cname ) , fn , __VA_ARGS__ )
2020-07-23 14:58:19 +08:00
# define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \
2021-01-02 17:15:39 +08:00
PYBIND11_OVERRIDE_PURE ( PYBIND11_TYPE ( ret_type ) , PYBIND11_TYPE ( cname ) , fn , __VA_ARGS__ ) ;
2020-07-23 14:58:19 +08:00
2021-01-02 17:15:39 +08:00
PYBIND11_NAMESPACE_END ( PYBIND11_NAMESPACE )
2020-07-23 14:58:19 +08:00
# if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
# pragma warning(pop)
# elif defined(__GNUG__) && !defined(__clang__)
# pragma GCC diagnostic pop
# endif