Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pybind11
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
pybind11
Commits
8e5ca010
Commit
8e5ca010
authored
Jan 24, 2021
by
Ralf W. Grosse-Kunstleve
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding py::smart_holder support to py::class_, purging py::classh completely.
parent
a0cf20c8
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
78 additions
and
332 deletions
+78
-332
include/pybind11/cast.h
+3
-1
include/pybind11/classh.h
+1
-317
include/pybind11/detail/classh_type_casters.h
+36
-0
include/pybind11/pybind11.h
+17
-1
tests/classh_module_local_0.cpp
+1
-0
tests/classh_module_local_1.cpp
+2
-1
tests/classh_module_local_2.cpp
+2
-1
tests/test_classh_inheritance.cpp
+6
-5
tests/test_classh_wip.cpp
+7
-5
tests/test_unique_ptr_member.cpp
+3
-1
No files found.
include/pybind11/cast.h
View file @
8e5ca010
...
@@ -1636,6 +1636,7 @@ using type_caster_holder = conditional_t<is_copy_constructible<holder_type>::val
...
@@ -1636,6 +1636,7 @@ using type_caster_holder = conditional_t<is_copy_constructible<holder_type>::val
copyable_holder_caster
<
type
,
holder_type
>
,
copyable_holder_caster
<
type
,
holder_type
>
,
move_only_holder_caster
<
type
,
holder_type
>>
;
move_only_holder_caster
<
type
,
holder_type
>>
;
template
<
typename
T
,
bool
Value
=
false
>
struct
is_smart_holder
{
static
constexpr
bool
value
=
Value
;
};
template
<
typename
T
,
bool
Value
=
false
>
struct
always_construct_holder
{
static
constexpr
bool
value
=
Value
;
};
template
<
typename
T
,
bool
Value
=
false
>
struct
always_construct_holder
{
static
constexpr
bool
value
=
Value
;
};
/// Create a specialization for custom holder types (silently ignores std::shared_ptr)
/// Create a specialization for custom holder types (silently ignores std::shared_ptr)
...
@@ -1650,7 +1651,8 @@ template <typename T, bool Value = false> struct always_construct_holder { stati
...
@@ -1650,7 +1651,8 @@ template <typename T, bool Value = false> struct always_construct_holder { stati
// PYBIND11_DECLARE_HOLDER_TYPE holder types:
// PYBIND11_DECLARE_HOLDER_TYPE holder types:
template
<
typename
base
,
typename
holder
>
struct
is_holder_type
:
template
<
typename
base
,
typename
holder
>
struct
is_holder_type
:
std
::
is_base_of
<
detail
::
type_caster_holder
<
base
,
holder
>
,
detail
::
type_caster
<
holder
>>
{};
detail
::
any_of
<
std
::
is_base_of
<
detail
::
type_caster_holder
<
base
,
holder
>
,
detail
::
type_caster
<
holder
>>
,
detail
::
is_smart_holder
<
holder
>>
{};
// Specialization for always-supported unique_ptr holders:
// Specialization for always-supported unique_ptr holders:
template
<
typename
base
,
typename
deleter
>
struct
is_holder_type
<
base
,
std
::
unique_ptr
<
base
,
deleter
>>
:
template
<
typename
base
,
typename
deleter
>
struct
is_holder_type
<
base
,
std
::
unique_ptr
<
base
,
deleter
>>
:
std
::
true_type
{};
std
::
true_type
{};
...
...
include/pybind11/classh.h
View file @
8e5ca010
#pragma once
#pragma once
#include "detail/classh_type_casters.h"
#include "detail/classh_type_casters.h"
#include "pybind11.h"
#include "smart_holder_poc.h"
#include "smart_holder_poc.h"
PYBIND11_NAMESPACE_BEGIN
(
PYBIND11_NAMESPACE
)
PYBIND11_NAMESPACE_BEGIN
(
PYBIND11_NAMESPACE
)
// clang-format off
using
pybindit
::
memory
::
smart_holder
;
template
<
typename
type_
,
typename
...
options
>
class
classh
:
public
detail
::
generic_type
{
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_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
=
pybindit
::
memory
::
smart_holder
;
static_assert
(
detail
::
all_of
<
is_valid_class_option
<
options
>
...
>::
value
,
"Unknown/invalid classh template parameters provided"
);
static_assert
(
!
has_alias
||
std
::
is_polymorphic
<
type
>::
value
,
"Cannot use an alias class with a non-polymorphic type"
);
PYBIND11_OBJECT
(
classh
,
generic_type
,
PyType_Check
)
template
<
typename
...
Extra
>
classh
(
handle
scope
,
const
char
*
name
,
const
Extra
&
...
extra
)
{
using
namespace
detail
;
// MI can only be specified via classh 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 classh 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
=
false
;
set_operator_new
<
type
>
(
&
record
);
/* Register base classes specified via template arguments to classh, 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
,
&
modified_type_caster_generic_load_impl
::
local_load
);
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
>
classh
&
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
...);
add_class_method
(
*
this
,
name_
,
cf
);
return
*
this
;
}
template
<
typename
Func
,
typename
...
Extra
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
def
(
const
detail
::
initimpl
::
constructor
<
Args
...
>
&
init
,
const
Extra
&
...
extra
)
{
init
.
execute
(
*
this
,
extra
...);
return
*
this
;
}
template
<
typename
...
Args
,
typename
...
Extra
>
classh
&
def
(
const
detail
::
initimpl
::
alias_constructor
<
Args
...
>
&
init
,
const
Extra
&
...
extra
)
{
init
.
execute
(
*
this
,
extra
...);
return
*
this
;
}
template
<
typename
...
Args
,
typename
...
Extra
>
classh
&
def
(
detail
::
initimpl
::
factory
<
Args
...
>
&&
init
,
const
Extra
&
...
extra
)
{
std
::
move
(
init
).
execute
(
*
this
,
extra
...);
return
*
this
;
}
template
<
typename
...
Args
,
typename
...
Extra
>
classh
&
def
(
detail
::
initimpl
::
pickle_factory
<
Args
...
>
&&
pf
,
const
Extra
&
...
extra
)
{
std
::
move
(
pf
).
execute
(
*
this
,
extra
...);
return
*
this
;
}
template
<
typename
Func
>
classh
&
def_buffer
(
Func
&&
func
)
{
struct
capture
{
Func
func
;
};
auto
*
ptr
=
new
capture
{
std
::
forward
<
Func
>
(
func
)
};
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
);
weakref
(
m_ptr
,
cpp_function
([
ptr
](
handle
wr
)
{
delete
ptr
;
wr
.
dec_ref
();
})).
release
();
return
*
this
;
}
template
<
typename
Return
,
typename
Class
,
typename
...
Args
>
classh
&
def_buffer
(
Return
(
Class
::*
func
)(
Args
...))
{
return
def_buffer
([
func
]
(
type
&
obj
)
{
return
(
obj
.
*
func
)();
});
}
template
<
typename
Return
,
typename
Class
,
typename
...
Args
>
classh
&
def_buffer
(
Return
(
Class
::*
func
)(
Args
...)
const
)
{
return
def_buffer
([
func
]
(
const
type
&
obj
)
{
return
(
obj
.
*
func
)();
});
}
template
<
typename
C
,
typename
D
,
typename
...
Extra
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
>
classh
&
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
:
// clang-format on
static
void
init_instance
(
detail
::
instance
*
inst
,
const
void
*
holder_const_void_ptr
)
{
// Need for const_cast is a consequence of the type_info::init_instance type:
// void (*init_instance)(instance *, const void *);
auto
holder_void_ptr
=
const_cast
<
void
*>
(
holder_const_void_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
();
}
if
(
holder_void_ptr
)
{
// Note: inst->owned ignored.
auto
holder_ptr
=
static_cast
<
holder_type
*>
(
holder_void_ptr
);
new
(
std
::
addressof
(
v_h
.
holder
<
holder_type
>
()))
holder_type
(
std
::
move
(
*
holder_ptr
));
}
else
if
(
inst
->
owned
)
{
new
(
std
::
addressof
(
v_h
.
holder
<
holder_type
>
()))
holder_type
(
holder_type
::
from_raw_ptr_take_ownership
(
v_h
.
value_ptr
<
type
>
()));
}
else
{
new
(
std
::
addressof
(
v_h
.
holder
<
holder_type
>
()))
holder_type
(
holder_type
::
from_raw_ptr_unowned
(
v_h
.
value_ptr
<
type
>
()));
}
v_h
.
set_holder_constructed
();
}
// clang-format off
/// Deallocates an instance; via holder, if constructed; otherwise via operator delete.
static
void
dealloc
(
detail
::
value_and_holder
&
v_h
)
{
// 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
;
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
;
}
};
PYBIND11_NAMESPACE_END
(
PYBIND11_NAMESPACE
)
PYBIND11_NAMESPACE_END
(
PYBIND11_NAMESPACE
)
include/pybind11/detail/classh_type_casters.h
View file @
8e5ca010
...
@@ -631,5 +631,41 @@ struct classh_type_caster<std::unique_ptr<T const>> : smart_holder_type_caster_l
...
@@ -631,5 +631,41 @@ struct classh_type_caster<std::unique_ptr<T const>> : smart_holder_type_caster_l
} \
} \
}
}
template
<>
struct
is_smart_holder
<
pybindit
::
memory
::
smart_holder
>
:
is_smart_holder
<
pybindit
::
memory
::
smart_holder
,
true
>
{
static
decltype
(
&
modified_type_caster_generic_load_impl
::
local_load
)
get_type_caster_local_load_function_ptr
()
{
return
&
modified_type_caster_generic_load_impl
::
local_load
;
}
template
<
typename
T
>
static
void
init_instance_for_type
(
detail
::
instance
*
inst
,
const
void
*
holder_const_void_ptr
)
{
// Need for const_cast is a consequence of the type_info::init_instance type:
// void (*init_instance)(instance *, const void *);
auto
holder_void_ptr
=
const_cast
<
void
*>
(
holder_const_void_ptr
);
auto
v_h
=
inst
->
get_value_and_holder
(
detail
::
get_type_info
(
typeid
(
T
)));
if
(
!
v_h
.
instance_registered
())
{
register_instance
(
inst
,
v_h
.
value_ptr
(),
v_h
.
type
);
v_h
.
set_instance_registered
();
}
using
holder_type
=
pybindit
::
memory
::
smart_holder
;
if
(
holder_void_ptr
)
{
// Note: inst->owned ignored.
auto
holder_ptr
=
static_cast
<
holder_type
*>
(
holder_void_ptr
);
new
(
std
::
addressof
(
v_h
.
holder
<
holder_type
>
()))
holder_type
(
std
::
move
(
*
holder_ptr
));
}
else
if
(
inst
->
owned
)
{
new
(
std
::
addressof
(
v_h
.
holder
<
holder_type
>
()))
holder_type
(
holder_type
::
from_raw_ptr_take_ownership
(
v_h
.
value_ptr
<
T
>
()));
}
else
{
new
(
std
::
addressof
(
v_h
.
holder
<
holder_type
>
()))
holder_type
(
holder_type
::
from_raw_ptr_unowned
(
v_h
.
value_ptr
<
T
>
()));
}
v_h
.
set_holder_constructed
();
}
};
}
// namespace detail
}
// namespace detail
}
// namespace pybind11
}
// namespace pybind11
include/pybind11/pybind11.h
View file @
8e5ca010
...
@@ -1295,7 +1295,7 @@ public:
...
@@ -1295,7 +1295,7 @@ public:
/* Process optional arguments, if any */
/* Process optional arguments, if any */
process_attributes
<
Extra
...
>::
init
(
extra
...,
&
record
);
process_attributes
<
Extra
...
>::
init
(
extra
...,
&
record
);
generic_type
::
initialize
(
record
,
&
type_caster_generic
::
local_loa
d
);
generic_type
_initialize
(
recor
d
);
if
(
has_alias
)
{
if
(
has_alias
)
{
auto
&
instances
=
record
.
module_local
?
registered_local_types_cpp
()
:
get_internals
().
registered_types_cpp
;
auto
&
instances
=
record
.
module_local
?
registered_local_types_cpp
()
:
get_internals
().
registered_types_cpp
;
...
@@ -1503,6 +1503,16 @@ public:
...
@@ -1503,6 +1503,16 @@ public:
}
}
private
:
private
:
template
<
typename
H
=
holder_type
,
detail
::
enable_if_t
<!
detail
::
is_smart_holder
<
H
>::
value
,
int
>
=
0
>
void
generic_type_initialize
(
const
detail
::
type_record
&
record
)
{
generic_type
::
initialize
(
record
,
&
detail
::
type_caster_generic
::
local_load
);
}
template
<
typename
H
=
holder_type
,
detail
::
enable_if_t
<
detail
::
is_smart_holder
<
H
>::
value
,
int
>
=
0
>
void
generic_type_initialize
(
const
detail
::
type_record
&
record
)
{
generic_type
::
initialize
(
record
,
detail
::
is_smart_holder
<
H
>::
get_type_caster_local_load_function_ptr
());
}
/// Initialize holder object, variant 1: object derives from enable_shared_from_this
/// Initialize holder object, variant 1: object derives from enable_shared_from_this
template
<
typename
T
>
template
<
typename
T
>
static
void
init_holder
(
detail
::
instance
*
inst
,
detail
::
value_and_holder
&
v_h
,
static
void
init_holder
(
detail
::
instance
*
inst
,
detail
::
value_and_holder
&
v_h
,
...
@@ -1547,6 +1557,7 @@ private:
...
@@ -1547,6 +1557,7 @@ private:
/// instance. Should be called as soon as the `type` value_ptr is set for an instance. Takes an
/// 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
/// 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.
/// `.owned`, a new holder will be constructed to manage the value pointer.
template
<
typename
H
=
holder_type
,
detail
::
enable_if_t
<!
detail
::
is_smart_holder
<
H
>::
value
,
int
>
=
0
>
static
void
init_instance
(
detail
::
instance
*
inst
,
const
void
*
holder_ptr
)
{
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
)));
auto
v_h
=
inst
->
get_value_and_holder
(
detail
::
get_type_info
(
typeid
(
type
)));
if
(
!
v_h
.
instance_registered
())
{
if
(
!
v_h
.
instance_registered
())
{
...
@@ -1556,6 +1567,11 @@ private:
...
@@ -1556,6 +1567,11 @@ private:
init_holder
(
inst
,
v_h
,
(
const
holder_type
*
)
holder_ptr
,
v_h
.
value_ptr
<
type
>
());
init_holder
(
inst
,
v_h
,
(
const
holder_type
*
)
holder_ptr
,
v_h
.
value_ptr
<
type
>
());
}
}
template
<
typename
H
=
holder_type
,
detail
::
enable_if_t
<
detail
::
is_smart_holder
<
H
>::
value
,
int
>
=
0
>
static
void
init_instance
(
detail
::
instance
*
inst
,
const
void
*
holder_ptr
)
{
detail
::
is_smart_holder
<
H
>::
template
init_instance_for_type
<
type
>
(
inst
,
holder_ptr
);
}
/// Deallocates an instance; via holder, if constructed; otherwise via operator delete.
/// Deallocates an instance; via holder, if constructed; otherwise via operator delete.
static
void
dealloc
(
detail
::
value_and_holder
&
v_h
)
{
static
void
dealloc
(
detail
::
value_and_holder
&
v_h
)
{
// We could be deallocating because we are cleaning up after a Python exception.
// We could be deallocating because we are cleaning up after a Python exception.
...
...
tests/classh_module_local_0.cpp
View file @
8e5ca010
#include <pybind11/classh.h>
#include <pybind11/classh.h>
#include <pybind11/pybind11.h>
#include <string>
#include <string>
...
...
tests/classh_module_local_1.cpp
View file @
8e5ca010
// Identical to classh_module_local_2.cpp, except 2 replaced with 1.
// Identical to classh_module_local_2.cpp, except 2 replaced with 1.
#include <pybind11/classh.h>
#include <pybind11/classh.h>
#include <pybind11/pybind11.h>
#include <string>
#include <string>
...
@@ -21,7 +22,7 @@ PYBIND11_MODULE(classh_module_local_1, m) {
...
@@ -21,7 +22,7 @@ PYBIND11_MODULE(classh_module_local_1, m) {
namespace
py
=
pybind11
;
namespace
py
=
pybind11
;
using
namespace
pybind11_tests
::
classh_module_local
;
using
namespace
pybind11_tests
::
classh_module_local
;
py
::
class
h
<
atyp
>
(
m
,
"atyp"
,
py
::
module_local
())
py
::
class
_
<
atyp
,
py
::
smart_holder
>
(
m
,
"atyp"
,
py
::
module_local
())
.
def
(
py
::
init
([](
const
std
::
string
&
mtxt
)
{
.
def
(
py
::
init
([](
const
std
::
string
&
mtxt
)
{
atyp
obj
;
atyp
obj
;
obj
.
mtxt
=
mtxt
;
obj
.
mtxt
=
mtxt
;
...
...
tests/classh_module_local_2.cpp
View file @
8e5ca010
// Identical to classh_module_local_1.cpp, except 1 replaced with 2.
// Identical to classh_module_local_1.cpp, except 1 replaced with 2.
#include <pybind11/classh.h>
#include <pybind11/classh.h>
#include <pybind11/pybind11.h>
#include <string>
#include <string>
...
@@ -21,7 +22,7 @@ PYBIND11_MODULE(classh_module_local_2, m) {
...
@@ -21,7 +22,7 @@ PYBIND11_MODULE(classh_module_local_2, m) {
namespace
py
=
pybind11
;
namespace
py
=
pybind11
;
using
namespace
pybind11_tests
::
classh_module_local
;
using
namespace
pybind11_tests
::
classh_module_local
;
py
::
class
h
<
atyp
>
(
m
,
"atyp"
,
py
::
module_local
())
py
::
class
_
<
atyp
,
py
::
smart_holder
>
(
m
,
"atyp"
,
py
::
module_local
())
.
def
(
py
::
init
([](
const
std
::
string
&
mtxt
)
{
.
def
(
py
::
init
([](
const
std
::
string
&
mtxt
)
{
atyp
obj
;
atyp
obj
;
obj
.
mtxt
=
mtxt
;
obj
.
mtxt
=
mtxt
;
...
...
tests/test_classh_inheritance.cpp
View file @
8e5ca010
...
@@ -67,8 +67,8 @@ namespace pybind11_tests {
...
@@ -67,8 +67,8 @@ namespace pybind11_tests {
namespace
classh_inheritance
{
namespace
classh_inheritance
{
TEST_SUBMODULE
(
classh_inheritance
,
m
)
{
TEST_SUBMODULE
(
classh_inheritance
,
m
)
{
py
::
class
h
<
base
>
(
m
,
"base"
);
py
::
class
_
<
base
,
py
::
smart_holder
>
(
m
,
"base"
);
py
::
class
h
<
drvd
,
base
>
(
m
,
"drvd"
);
py
::
class
_
<
drvd
,
base
,
py
::
smart_holder
>
(
m
,
"drvd"
);
auto
rvto
=
py
::
return_value_policy
::
take_ownership
;
auto
rvto
=
py
::
return_value_policy
::
take_ownership
;
...
@@ -82,9 +82,10 @@ TEST_SUBMODULE(classh_inheritance, m) {
...
@@ -82,9 +82,10 @@ TEST_SUBMODULE(classh_inheritance, m) {
m
.
def
(
"pass_shcp_base"
,
pass_shcp_base
);
m
.
def
(
"pass_shcp_base"
,
pass_shcp_base
);
m
.
def
(
"pass_shcp_drvd"
,
pass_shcp_drvd
);
m
.
def
(
"pass_shcp_drvd"
,
pass_shcp_drvd
);
py
::
classh
<
base1
>
(
m
,
"base1"
).
def
(
py
::
init
<>
());
// __init__ needed for Python inheritance.
// __init__ needed for Python inheritance.
py
::
classh
<
base2
>
(
m
,
"base2"
).
def
(
py
::
init
<>
());
py
::
class_
<
base1
,
py
::
smart_holder
>
(
m
,
"base1"
).
def
(
py
::
init
<>
());
py
::
classh
<
drvd2
,
base1
,
base2
>
(
m
,
"drvd2"
);
py
::
class_
<
base2
,
py
::
smart_holder
>
(
m
,
"base2"
).
def
(
py
::
init
<>
());
py
::
class_
<
drvd2
,
base1
,
base2
,
py
::
smart_holder
>
(
m
,
"drvd2"
);
m
.
def
(
"rtrn_mptr_drvd2"
,
rtrn_mptr_drvd2
,
rvto
);
m
.
def
(
"rtrn_mptr_drvd2"
,
rtrn_mptr_drvd2
,
rvto
);
m
.
def
(
"rtrn_mptr_drvd2_up_cast1"
,
rtrn_mptr_drvd2_up_cast1
,
rvto
);
m
.
def
(
"rtrn_mptr_drvd2_up_cast1"
,
rtrn_mptr_drvd2_up_cast1
,
rvto
);
...
...
tests/test_classh_wip.cpp
View file @
8e5ca010
...
@@ -57,11 +57,13 @@ namespace classh_wip {
...
@@ -57,11 +57,13 @@ namespace classh_wip {
TEST_SUBMODULE
(
classh_wip
,
m
)
{
TEST_SUBMODULE
(
classh_wip
,
m
)
{
namespace
py
=
pybind11
;
namespace
py
=
pybind11
;
py
::
classh
<
atyp
>
(
m
,
"atyp"
).
def
(
py
::
init
<>
()).
def
(
py
::
init
([](
const
std
::
string
&
mtxt
)
{
py
::
class_
<
atyp
,
py
::
smart_holder
>
(
m
,
"atyp"
)
atyp
obj
;
.
def
(
py
::
init
<>
())
obj
.
mtxt
=
mtxt
;
.
def
(
py
::
init
([](
const
std
::
string
&
mtxt
)
{
return
obj
;
atyp
obj
;
}));
obj
.
mtxt
=
mtxt
;
return
obj
;
}));
m
.
def
(
"rtrn_valu_atyp"
,
rtrn_valu_atyp
);
m
.
def
(
"rtrn_valu_atyp"
,
rtrn_valu_atyp
);
m
.
def
(
"rtrn_rref_atyp"
,
rtrn_rref_atyp
);
m
.
def
(
"rtrn_rref_atyp"
,
rtrn_rref_atyp
);
...
...
tests/test_unique_ptr_member.cpp
View file @
8e5ca010
...
@@ -46,7 +46,9 @@ namespace pybind11_tests {
...
@@ -46,7 +46,9 @@ namespace pybind11_tests {
namespace
unique_ptr_member
{
namespace
unique_ptr_member
{
TEST_SUBMODULE
(
unique_ptr_member
,
m
)
{
TEST_SUBMODULE
(
unique_ptr_member
,
m
)
{
py
::
classh
<
pointee
>
(
m
,
"pointee"
).
def
(
py
::
init
<>
()).
def
(
"get_int"
,
&
pointee
::
get_int
);
py
::
class_
<
pointee
,
py
::
smart_holder
>
(
m
,
"pointee"
)
.
def
(
py
::
init
<>
())
.
def
(
"get_int"
,
&
pointee
::
get_int
);
m
.
def
(
"make_unique_pointee"
,
make_unique_pointee
);
m
.
def
(
"make_unique_pointee"
,
make_unique_pointee
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment