Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
e315e1fe
Unverified
Commit
e315e1fe
authored
Oct 04, 2021
by
Henry Schreiner
Browse files
Merge branch 'master' into stable
parents
71fd5241
97976c16
Changes
143
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
529 additions
and
52 deletions
+529
-52
tests/test_numpy_vectorize.py
tests/test_numpy_vectorize.py
+1
-0
tests/test_opaque_types.py
tests/test_opaque_types.py
+2
-1
tests/test_operator_overloading.py
tests/test_operator_overloading.py
+2
-1
tests/test_pickling.cpp
tests/test_pickling.cpp
+2
-2
tests/test_pickling.py
tests/test_pickling.py
+0
-1
tests/test_pytypes.cpp
tests/test_pytypes.cpp
+123
-0
tests/test_pytypes.py
tests/test_pytypes.py
+64
-4
tests/test_sequences_and_iterators.cpp
tests/test_sequences_and_iterators.cpp
+109
-8
tests/test_sequences_and_iterators.py
tests/test_sequences_and_iterators.py
+52
-1
tests/test_smart_ptr.cpp
tests/test_smart_ptr.cpp
+17
-16
tests/test_stl.cpp
tests/test_stl.cpp
+2
-1
tests/test_stl.py
tests/test_stl.py
+1
-2
tests/test_stl_binders.cpp
tests/test_stl_binders.cpp
+1
-1
tests/test_stl_binders.py
tests/test_stl_binders.py
+29
-2
tests/test_tagbased_polymorphic.cpp
tests/test_tagbased_polymorphic.cpp
+10
-8
tests/test_thread.cpp
tests/test_thread.cpp
+66
-0
tests/test_thread.py
tests/test_thread.py
+44
-0
tests/test_virtual_functions.cpp
tests/test_virtual_functions.cpp
+2
-1
tools/libsize.py
tools/libsize.py
+2
-1
tools/make_changelog.py
tools/make_changelog.py
+0
-2
No files found.
tests/test_numpy_vectorize.py
View file @
e315e1fe
# -*- coding: utf-8 -*-
import
pytest
from
pybind11_tests
import
numpy_vectorize
as
m
np
=
pytest
.
importorskip
(
"numpy"
)
...
...
tests/test_opaque_types.py
View file @
e315e1fe
# -*- coding: utf-8 -*-
import
pytest
from
pybind11_tests
import
opaque_types
as
m
from
pybind11_tests
import
ConstructorStats
,
UserType
from
pybind11_tests
import
opaque_types
as
m
def
test_string_list
():
...
...
tests/test_operator_overloading.py
View file @
e315e1fe
# -*- coding: utf-8 -*-
import
pytest
from
pybind11_tests
import
operators
as
m
from
pybind11_tests
import
ConstructorStats
from
pybind11_tests
import
operators
as
m
def
test_operator_overloading
():
...
...
tests/test_pickling.cpp
View file @
e315e1fe
...
...
@@ -67,7 +67,7 @@ TEST_SUBMODULE(pickling, m) {
// test_roundtrip
class
Pickleable
{
public:
Pickleable
(
const
std
::
string
&
value
)
:
m_value
(
value
)
{
}
explicit
Pickleable
(
const
std
::
string
&
value
)
:
m_value
(
value
)
{
}
const
std
::
string
&
value
()
const
{
return
m_value
;
}
void
setExtra1
(
int
extra1
)
{
m_extra1
=
extra1
;
}
...
...
@@ -132,7 +132,7 @@ TEST_SUBMODULE(pickling, m) {
// test_roundtrip_with_dict
class
PickleableWithDict
{
public:
PickleableWithDict
(
const
std
::
string
&
value
)
:
value
(
value
)
{
}
explicit
PickleableWithDict
(
const
std
::
string
&
value
)
:
value
(
value
)
{
}
std
::
string
value
;
int
extra
;
...
...
tests/test_pickling.py
View file @
e315e1fe
...
...
@@ -2,7 +2,6 @@
import
pytest
import
env
# noqa: F401
from
pybind11_tests
import
pickling
as
m
try
:
...
...
tests/test_pytypes.cpp
View file @
e315e1fe
...
...
@@ -20,6 +20,11 @@ TEST_SUBMODULE(pytypes, m) {
// test_iterable
m
.
def
(
"get_iterable"
,
[]{
return
py
::
iterable
();});
// test_list
m
.
def
(
"list_no_args"
,
[]()
{
return
py
::
list
{};
});
m
.
def
(
"list_ssize_t"
,
[]()
{
return
py
::
list
{(
py
::
ssize_t
)
0
};
});
m
.
def
(
"list_size_t"
,
[]()
{
return
py
::
list
{(
py
::
size_t
)
0
};
});
m
.
def
(
"list_insert_ssize_t"
,
[](
py
::
list
*
l
)
{
return
l
->
insert
((
py
::
ssize_t
)
1
,
83
);
});
m
.
def
(
"list_insert_size_t"
,
[](
py
::
list
*
l
)
{
return
l
->
insert
((
py
::
size_t
)
3
,
57
);
});
m
.
def
(
"get_list"
,
[]()
{
py
::
list
list
;
list
.
append
(
"value"
);
...
...
@@ -70,7 +75,25 @@ TEST_SUBMODULE(pytypes, m) {
m
.
def
(
"dict_contains"
,
[](
const
py
::
dict
&
dict
,
const
char
*
val
)
{
return
dict
.
contains
(
val
);
});
// test_tuple
m
.
def
(
"tuple_no_args"
,
[]()
{
return
py
::
tuple
{};
});
m
.
def
(
"tuple_ssize_t"
,
[]()
{
return
py
::
tuple
{(
py
::
ssize_t
)
0
};
});
m
.
def
(
"tuple_size_t"
,
[]()
{
return
py
::
tuple
{(
py
::
size_t
)
0
};
});
m
.
def
(
"get_tuple"
,
[]()
{
return
py
::
make_tuple
(
42
,
py
::
none
(),
"spam"
);
});
#if PY_VERSION_HEX >= 0x03030000
// test_simple_namespace
m
.
def
(
"get_simple_namespace"
,
[]()
{
auto
ns
=
py
::
make_simple_namespace
(
"attr"
_a
=
42
,
"x"
_a
=
"foo"
,
"wrong"
_a
=
1
);
py
::
delattr
(
ns
,
"wrong"
);
py
::
setattr
(
ns
,
"right"
,
py
::
int_
(
2
));
return
ns
;
});
#endif
// test_str
m
.
def
(
"str_from_char_ssize_t"
,
[]()
{
return
py
::
str
{
"red"
,
(
py
::
ssize_t
)
3
};
});
m
.
def
(
"str_from_char_size_t"
,
[]()
{
return
py
::
str
{
"blue"
,
(
py
::
size_t
)
4
};
});
m
.
def
(
"str_from_string"
,
[]()
{
return
py
::
str
(
std
::
string
(
"baz"
));
});
m
.
def
(
"str_from_bytes"
,
[]()
{
return
py
::
str
(
py
::
bytes
(
"boo"
,
3
));
});
m
.
def
(
"str_from_object"
,
[](
const
py
::
object
&
obj
)
{
return
py
::
str
(
obj
);
});
...
...
@@ -87,10 +110,14 @@ TEST_SUBMODULE(pytypes, m) {
});
// test_bytes
m
.
def
(
"bytes_from_char_ssize_t"
,
[]()
{
return
py
::
bytes
{
"green"
,
(
py
::
ssize_t
)
5
};
});
m
.
def
(
"bytes_from_char_size_t"
,
[]()
{
return
py
::
bytes
{
"purple"
,
(
py
::
size_t
)
6
};
});
m
.
def
(
"bytes_from_string"
,
[]()
{
return
py
::
bytes
(
std
::
string
(
"foo"
));
});
m
.
def
(
"bytes_from_str"
,
[]()
{
return
py
::
bytes
(
py
::
str
(
"bar"
,
3
));
});
// test bytearray
m
.
def
(
"bytearray_from_char_ssize_t"
,
[]()
{
return
py
::
bytearray
{
"$%"
,
(
py
::
ssize_t
)
2
};
});
m
.
def
(
"bytearray_from_char_size_t"
,
[]()
{
return
py
::
bytearray
{
"@$!"
,
(
py
::
size_t
)
3
};
});
m
.
def
(
"bytearray_from_string"
,
[]()
{
return
py
::
bytearray
(
std
::
string
(
"foo"
));
});
m
.
def
(
"bytearray_size"
,
[]()
{
return
py
::
bytearray
(
"foo"
).
size
();
});
...
...
@@ -434,4 +461,100 @@ TEST_SUBMODULE(pytypes, m) {
m
.
def
(
"weakref_from_object"
,
[](
const
py
::
object
&
o
)
{
return
py
::
weakref
(
o
);
});
m
.
def
(
"weakref_from_object_and_function"
,
[](
py
::
object
o
,
py
::
function
f
)
{
return
py
::
weakref
(
std
::
move
(
o
),
std
::
move
(
f
));
});
// See PR #3263 for background (https://github.com/pybind/pybind11/pull/3263):
// pytypes.h could be changed to enforce the "most correct" user code below, by removing
// `const` from iterator `reference` using type aliases, but that will break existing
// user code.
#if (defined(__APPLE__) && defined(__clang__)) || defined(PYPY_VERSION)
// This is "most correct" and enforced on these platforms.
# define PYBIND11_AUTO_IT auto it
#else
// This works on many platforms and is (unfortunately) reflective of existing user code.
// NOLINTNEXTLINE(bugprone-macro-parentheses)
# define PYBIND11_AUTO_IT auto &it
#endif
m
.
def
(
"tuple_iterator"
,
[]()
{
auto
tup
=
py
::
make_tuple
(
5
,
7
);
int
tup_sum
=
0
;
for
(
PYBIND11_AUTO_IT
:
tup
)
{
tup_sum
+=
it
.
cast
<
int
>
();
}
return
tup_sum
;
});
m
.
def
(
"dict_iterator"
,
[]()
{
py
::
dict
dct
;
dct
[
py
::
int_
(
3
)]
=
5
;
dct
[
py
::
int_
(
7
)]
=
11
;
int
kv_sum
=
0
;
for
(
PYBIND11_AUTO_IT
:
dct
)
{
kv_sum
+=
it
.
first
.
cast
<
int
>
()
*
100
+
it
.
second
.
cast
<
int
>
();
}
return
kv_sum
;
});
m
.
def
(
"passed_iterator"
,
[](
const
py
::
iterator
&
py_it
)
{
int
elem_sum
=
0
;
for
(
PYBIND11_AUTO_IT
:
py_it
)
{
elem_sum
+=
it
.
cast
<
int
>
();
}
return
elem_sum
;
});
#undef PYBIND11_AUTO_IT
// Tests below this line are for pybind11 IMPLEMENTATION DETAILS:
m
.
def
(
"sequence_item_get_ssize_t"
,
[](
const
py
::
object
&
o
)
{
return
py
::
detail
::
accessor_policies
::
sequence_item
::
get
(
o
,
(
py
::
ssize_t
)
1
);
});
m
.
def
(
"sequence_item_set_ssize_t"
,
[](
const
py
::
object
&
o
)
{
auto
s
=
py
::
str
{
"peppa"
,
5
};
py
::
detail
::
accessor_policies
::
sequence_item
::
set
(
o
,
(
py
::
ssize_t
)
1
,
s
);
});
m
.
def
(
"sequence_item_get_size_t"
,
[](
const
py
::
object
&
o
)
{
return
py
::
detail
::
accessor_policies
::
sequence_item
::
get
(
o
,
(
py
::
size_t
)
2
);
});
m
.
def
(
"sequence_item_set_size_t"
,
[](
const
py
::
object
&
o
)
{
auto
s
=
py
::
str
{
"george"
,
6
};
py
::
detail
::
accessor_policies
::
sequence_item
::
set
(
o
,
(
py
::
size_t
)
2
,
s
);
});
m
.
def
(
"list_item_get_ssize_t"
,
[](
const
py
::
object
&
o
)
{
return
py
::
detail
::
accessor_policies
::
list_item
::
get
(
o
,
(
py
::
ssize_t
)
3
);
});
m
.
def
(
"list_item_set_ssize_t"
,
[](
const
py
::
object
&
o
)
{
auto
s
=
py
::
str
{
"rebecca"
,
7
};
py
::
detail
::
accessor_policies
::
list_item
::
set
(
o
,
(
py
::
ssize_t
)
3
,
s
);
});
m
.
def
(
"list_item_get_size_t"
,
[](
const
py
::
object
&
o
)
{
return
py
::
detail
::
accessor_policies
::
list_item
::
get
(
o
,
(
py
::
size_t
)
4
);
});
m
.
def
(
"list_item_set_size_t"
,
[](
const
py
::
object
&
o
)
{
auto
s
=
py
::
str
{
"richard"
,
7
};
py
::
detail
::
accessor_policies
::
list_item
::
set
(
o
,
(
py
::
size_t
)
4
,
s
);
});
m
.
def
(
"tuple_item_get_ssize_t"
,
[](
const
py
::
object
&
o
)
{
return
py
::
detail
::
accessor_policies
::
tuple_item
::
get
(
o
,
(
py
::
ssize_t
)
5
);
});
m
.
def
(
"tuple_item_set_ssize_t"
,
[]()
{
auto
s0
=
py
::
str
{
"emely"
,
5
};
auto
s1
=
py
::
str
{
"edmond"
,
6
};
auto
o
=
py
::
tuple
{
2
};
py
::
detail
::
accessor_policies
::
tuple_item
::
set
(
o
,
(
py
::
ssize_t
)
0
,
s0
);
py
::
detail
::
accessor_policies
::
tuple_item
::
set
(
o
,
(
py
::
ssize_t
)
1
,
s1
);
return
o
;
});
m
.
def
(
"tuple_item_get_size_t"
,
[](
const
py
::
object
&
o
)
{
return
py
::
detail
::
accessor_policies
::
tuple_item
::
get
(
o
,
(
py
::
size_t
)
6
);
});
m
.
def
(
"tuple_item_set_size_t"
,
[]()
{
auto
s0
=
py
::
str
{
"candy"
,
5
};
auto
s1
=
py
::
str
{
"cat"
,
3
};
auto
o
=
py
::
tuple
{
2
};
py
::
detail
::
accessor_policies
::
tuple_item
::
set
(
o
,
(
py
::
size_t
)
1
,
s1
);
py
::
detail
::
accessor_policies
::
tuple_item
::
set
(
o
,
(
py
::
size_t
)
0
,
s0
);
return
o
;
});
}
tests/test_pytypes.py
View file @
e315e1fe
# -*- coding: utf-8 -*-
from
__future__
import
division
import
pytest
import
sys
import
env
# noqa: F401
import
pytest
from
pybind11_tests
import
pytypes
as
m
import
env
# noqa: F401
from
pybind11_tests
import
debug_enabled
from
pybind11_tests
import
pytypes
as
m
def
test_int
(
doc
):
...
...
@@ -22,6 +23,15 @@ def test_iterable(doc):
def
test_list
(
capture
,
doc
):
assert
m
.
list_no_args
()
==
[]
assert
m
.
list_ssize_t
()
==
[]
assert
m
.
list_size_t
()
==
[]
lins
=
[
1
,
2
]
m
.
list_insert_ssize_t
(
lins
)
assert
lins
==
[
1
,
83
,
2
]
m
.
list_insert_size_t
(
lins
)
assert
lins
==
[
1
,
83
,
2
,
57
]
with
capture
:
lst
=
m
.
get_list
()
assert
lst
==
[
"inserted-0"
,
"overwritten"
,
"inserted-2"
]
...
...
@@ -98,7 +108,25 @@ def test_dict(capture, doc):
assert
m
.
dict_keyword_constructor
()
==
{
"x"
:
1
,
"y"
:
2
,
"z"
:
3
}
def
test_tuple
():
assert
m
.
tuple_no_args
()
==
()
assert
m
.
tuple_ssize_t
()
==
()
assert
m
.
tuple_size_t
()
==
()
assert
m
.
get_tuple
()
==
(
42
,
None
,
"spam"
)
@
pytest
.
mark
.
skipif
(
"env.PY2"
)
def
test_simple_namespace
():
ns
=
m
.
get_simple_namespace
()
assert
ns
.
attr
==
42
assert
ns
.
x
==
"foo"
assert
ns
.
right
==
2
assert
not
hasattr
(
ns
,
"wrong"
)
def
test_str
(
doc
):
assert
m
.
str_from_char_ssize_t
().
encode
().
decode
()
==
"red"
assert
m
.
str_from_char_size_t
().
encode
().
decode
()
==
"blue"
assert
m
.
str_from_string
().
encode
().
decode
()
==
"baz"
assert
m
.
str_from_bytes
().
encode
().
decode
()
==
"boo"
...
...
@@ -143,6 +171,8 @@ def test_str(doc):
def
test_bytes
(
doc
):
assert
m
.
bytes_from_char_ssize_t
().
decode
()
==
"green"
assert
m
.
bytes_from_char_size_t
().
decode
()
==
"purple"
assert
m
.
bytes_from_string
().
decode
()
==
"foo"
assert
m
.
bytes_from_str
().
decode
()
==
"bar"
...
...
@@ -152,6 +182,8 @@ def test_bytes(doc):
def
test_bytearray
(
doc
):
assert
m
.
bytearray_from_char_ssize_t
().
decode
()
==
"$%"
assert
m
.
bytearray_from_char_size_t
().
decode
()
==
"@$!"
assert
m
.
bytearray_from_string
().
decode
()
==
"foo"
assert
m
.
bytearray_size
()
==
len
(
"foo"
)
...
...
@@ -435,7 +467,8 @@ def test_issue2361():
assert
m
.
issue2361_str_implicit_copy_none
()
==
"None"
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
assert
m
.
issue2361_dict_implicit_copy_none
()
assert
"'NoneType' object is not iterable"
in
str
(
excinfo
.
value
)
assert
"NoneType"
in
str
(
excinfo
.
value
)
assert
"iterable"
in
str
(
excinfo
.
value
)
@
pytest
.
mark
.
parametrize
(
...
...
@@ -589,3 +622,30 @@ def test_weakref(create_weakref, create_weakref_with_callback):
del
obj
pytest
.
gc_collect
()
assert
callback
.
called
def
test_cpp_iterators
():
assert
m
.
tuple_iterator
()
==
12
assert
m
.
dict_iterator
()
==
305
+
711
assert
m
.
passed_iterator
(
iter
((
-
7
,
3
)))
==
-
4
def
test_implementation_details
():
lst
=
[
39
,
43
,
92
,
49
,
22
,
29
,
93
,
98
,
26
,
57
,
8
]
tup
=
tuple
(
lst
)
assert
m
.
sequence_item_get_ssize_t
(
lst
)
==
43
assert
m
.
sequence_item_set_ssize_t
(
lst
)
is
None
assert
lst
[
1
]
==
"peppa"
assert
m
.
sequence_item_get_size_t
(
lst
)
==
92
assert
m
.
sequence_item_set_size_t
(
lst
)
is
None
assert
lst
[
2
]
==
"george"
assert
m
.
list_item_get_ssize_t
(
lst
)
==
49
assert
m
.
list_item_set_ssize_t
(
lst
)
is
None
assert
lst
[
3
]
==
"rebecca"
assert
m
.
list_item_get_size_t
(
lst
)
==
22
assert
m
.
list_item_set_size_t
(
lst
)
is
None
assert
lst
[
4
]
==
"richard"
assert
m
.
tuple_item_get_ssize_t
(
tup
)
==
29
assert
m
.
tuple_item_set_ssize_t
()
==
(
"emely"
,
"edmond"
)
assert
m
.
tuple_item_get_size_t
(
tup
)
==
93
assert
m
.
tuple_item_set_size_t
()
==
(
"candy"
,
"cat"
)
tests/test_sequences_and_iterators.cpp
View file @
e315e1fe
...
...
@@ -15,12 +15,18 @@
#include <algorithm>
#include <utility>
#include <vector>
#ifdef PYBIND11_HAS_OPTIONAL
#include <optional>
#endif // PYBIND11_HAS_OPTIONAL
template
<
typename
T
>
class
NonZeroIterator
{
const
T
*
ptr_
;
public:
NonZeroIterator
(
const
T
*
ptr
)
:
ptr_
(
ptr
)
{}
explicit
NonZeroIterator
(
const
T
*
ptr
)
:
ptr_
(
ptr
)
{}
const
T
&
operator
*
()
const
{
return
*
ptr_
;
}
NonZeroIterator
&
operator
++
()
{
++
ptr_
;
return
*
this
;
}
};
...
...
@@ -32,6 +38,29 @@ bool operator==(const NonZeroIterator<std::pair<A, B>>& it, const NonZeroSentine
return
!
(
*
it
).
first
||
!
(
*
it
).
second
;
}
class
NonCopyableInt
{
public:
explicit
NonCopyableInt
(
int
value
)
:
value_
(
value
)
{}
NonCopyableInt
(
const
NonCopyableInt
&
)
=
delete
;
NonCopyableInt
(
NonCopyableInt
&&
other
)
noexcept
:
value_
(
other
.
value_
)
{
other
.
value_
=
-
1
;
// detect when an unwanted move occurs
}
NonCopyableInt
&
operator
=
(
const
NonCopyableInt
&
)
=
delete
;
NonCopyableInt
&
operator
=
(
NonCopyableInt
&&
other
)
noexcept
{
value_
=
other
.
value_
;
other
.
value_
=
-
1
;
// detect when an unwanted move occurs
return
*
this
;
}
int
get
()
const
{
return
value_
;
}
void
set
(
int
value
)
{
value_
=
value
;
}
~
NonCopyableInt
()
=
default
;
private:
int
value_
;
};
using
NonCopyableIntPair
=
std
::
pair
<
NonCopyableInt
,
NonCopyableInt
>
;
PYBIND11_MAKE_OPAQUE
(
std
::
vector
<
NonCopyableInt
>
);
PYBIND11_MAKE_OPAQUE
(
std
::
vector
<
NonCopyableIntPair
>
);
template
<
typename
PythonType
>
py
::
list
test_random_access_iterator
(
PythonType
x
)
{
if
(
x
.
size
()
<
5
)
...
...
@@ -77,9 +106,9 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
// test_sliceable
class
Sliceable
{
public:
Sliceable
(
int
n
)
:
size
(
n
)
{}
int
start
,
stop
,
step
;
int
size
;
explicit
Sliceable
(
int
n
)
:
size
(
n
)
{}
int
start
,
stop
,
step
;
int
size
;
};
py
::
class_
<
Sliceable
>
(
m
,
"Sliceable"
)
.
def
(
py
::
init
<
int
>
())
...
...
@@ -93,15 +122,27 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
return
std
::
make_tuple
(
istart
,
istop
,
istep
);
});
m
.
def
(
"make_forward_slice_size_t"
,
[]()
{
return
py
::
slice
(
0
,
-
1
,
1
);
});
m
.
def
(
"make_reversed_slice_object"
,
[]()
{
return
py
::
slice
(
py
::
none
(),
py
::
none
(),
py
::
int_
(
-
1
));
});
#ifdef PYBIND11_HAS_OPTIONAL
m
.
attr
(
"has_optional"
)
=
true
;
m
.
def
(
"make_reversed_slice_size_t_optional_verbose"
,
[]()
{
return
py
::
slice
(
std
::
nullopt
,
std
::
nullopt
,
-
1
);
});
// Warning: The following spelling may still compile if optional<> is not present and give wrong answers.
// Please use with caution.
m
.
def
(
"make_reversed_slice_size_t_optional"
,
[]()
{
return
py
::
slice
({},
{},
-
1
);
});
#else
m
.
attr
(
"has_optional"
)
=
false
;
#endif
// test_sequence
class
Sequence
{
public:
Sequence
(
size_t
size
)
:
m_size
(
size
)
{
explicit
Sequence
(
size_t
size
)
:
m_size
(
size
)
{
print_created
(
this
,
"of size"
,
m_size
);
m_data
=
new
float
[
size
];
memset
(
m_data
,
0
,
sizeof
(
float
)
*
size
);
}
Sequence
(
const
std
::
vector
<
float
>
&
value
)
:
m_size
(
value
.
size
())
{
explicit
Sequence
(
const
std
::
vector
<
float
>
&
value
)
:
m_size
(
value
.
size
())
{
print_created
(
this
,
"of size"
,
m_size
,
"from std::vector"
);
m_data
=
new
float
[
m_size
];
memcpy
(
m_data
,
&
value
[
0
],
sizeof
(
float
)
*
m_size
);
...
...
@@ -239,7 +280,7 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
class
StringMap
{
public:
StringMap
()
=
default
;
StringMap
(
std
::
unordered_map
<
std
::
string
,
std
::
string
>
init
)
explicit
StringMap
(
std
::
unordered_map
<
std
::
string
,
std
::
string
>
init
)
:
map
(
std
::
move
(
init
))
{}
void
set
(
const
std
::
string
&
key
,
std
::
string
val
)
{
map
[
key
]
=
std
::
move
(
val
);
}
...
...
@@ -271,13 +312,19 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
.
def
(
"items"
,
[](
const
StringMap
&
map
)
{
return
py
::
make_iterator
(
map
.
begin
(),
map
.
end
());
},
py
::
keep_alive
<
0
,
1
>
())
.
def
(
"values"
,
[](
const
StringMap
&
map
)
{
return
py
::
make_value_iterator
(
map
.
begin
(),
map
.
end
());
},
py
::
keep_alive
<
0
,
1
>
());
// test_generalized_iterators
class
IntPairs
{
public:
IntPairs
(
std
::
vector
<
std
::
pair
<
int
,
int
>>
data
)
:
data_
(
std
::
move
(
data
))
{}
explicit
IntPairs
(
std
::
vector
<
std
::
pair
<
int
,
int
>>
data
)
:
data_
(
std
::
move
(
data
))
{}
const
std
::
pair
<
int
,
int
>*
begin
()
const
{
return
data_
.
data
();
}
// .end() only required for py::make_iterator(self) overload
const
std
::
pair
<
int
,
int
>*
end
()
const
{
return
data_
.
data
()
+
data_
.
size
();
}
private:
std
::
vector
<
std
::
pair
<
int
,
int
>>
data_
;
};
...
...
@@ -289,8 +336,62 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
.
def
(
"nonzero_keys"
,
[](
const
IntPairs
&
s
)
{
return
py
::
make_key_iterator
(
NonZeroIterator
<
std
::
pair
<
int
,
int
>>
(
s
.
begin
()),
NonZeroSentinel
());
},
py
::
keep_alive
<
0
,
1
>
())
.
def
(
"nonzero_values"
,
[](
const
IntPairs
&
s
)
{
return
py
::
make_value_iterator
(
NonZeroIterator
<
std
::
pair
<
int
,
int
>>
(
s
.
begin
()),
NonZeroSentinel
());
},
py
::
keep_alive
<
0
,
1
>
())
// test single-argument make_iterator
.
def
(
"simple_iterator"
,
[](
IntPairs
&
self
)
{
return
py
::
make_iterator
(
self
);
},
py
::
keep_alive
<
0
,
1
>
())
.
def
(
"simple_keys"
,
[](
IntPairs
&
self
)
{
return
py
::
make_key_iterator
(
self
);
},
py
::
keep_alive
<
0
,
1
>
())
.
def
(
"simple_values"
,
[](
IntPairs
&
self
)
{
return
py
::
make_value_iterator
(
self
);
},
py
::
keep_alive
<
0
,
1
>
())
// Test iterator with an Extra (doesn't do anything useful, so not used
// at runtime, but tests need to be able to compile with the correct
// overload. See PR #3293.
.
def
(
"_make_iterator_extras"
,
[](
IntPairs
&
self
)
{
return
py
::
make_iterator
(
self
,
py
::
call_guard
<
int
>
());
},
py
::
keep_alive
<
0
,
1
>
())
.
def
(
"_make_key_extras"
,
[](
IntPairs
&
self
)
{
return
py
::
make_key_iterator
(
self
,
py
::
call_guard
<
int
>
());
},
py
::
keep_alive
<
0
,
1
>
())
.
def
(
"_make_value_extras"
,
[](
IntPairs
&
self
)
{
return
py
::
make_value_iterator
(
self
,
py
::
call_guard
<
int
>
());
},
py
::
keep_alive
<
0
,
1
>
())
;
// test_iterater_referencing
py
::
class_
<
NonCopyableInt
>
(
m
,
"NonCopyableInt"
)
.
def
(
py
::
init
<
int
>
())
.
def
(
"set"
,
&
NonCopyableInt
::
set
)
.
def
(
"__int__"
,
&
NonCopyableInt
::
get
)
;
py
::
class_
<
std
::
vector
<
NonCopyableInt
>>
(
m
,
"VectorNonCopyableInt"
)
.
def
(
py
::
init
<>
())
.
def
(
"append"
,
[](
std
::
vector
<
NonCopyableInt
>
&
vec
,
int
value
)
{
vec
.
emplace_back
(
value
);
})
.
def
(
"__iter__"
,
[](
std
::
vector
<
NonCopyableInt
>
&
vec
)
{
return
py
::
make_iterator
(
vec
.
begin
(),
vec
.
end
());
})
;
py
::
class_
<
std
::
vector
<
NonCopyableIntPair
>>
(
m
,
"VectorNonCopyableIntPair"
)
.
def
(
py
::
init
<>
())
.
def
(
"append"
,
[](
std
::
vector
<
NonCopyableIntPair
>
&
vec
,
const
std
::
pair
<
int
,
int
>
&
value
)
{
vec
.
emplace_back
(
NonCopyableInt
(
value
.
first
),
NonCopyableInt
(
value
.
second
));
})
.
def
(
"keys"
,
[](
std
::
vector
<
NonCopyableIntPair
>
&
vec
)
{
return
py
::
make_key_iterator
(
vec
.
begin
(),
vec
.
end
());
})
.
def
(
"values"
,
[](
std
::
vector
<
NonCopyableIntPair
>
&
vec
)
{
return
py
::
make_value_iterator
(
vec
.
begin
(),
vec
.
end
());
})
;
#if 0
// Obsolete: special data structure for exposing custom iterator types to python
...
...
tests/test_sequences_and_iterators.py
View file @
e315e1fe
# -*- coding: utf-8 -*-
import
pytest
from
pybind11_tests
import
sequences_and_iterators
as
m
from
pybind11_tests
import
ConstructorStats
from
pybind11_tests
import
sequences_and_iterators
as
m
def
isclose
(
a
,
b
,
rel_tol
=
1e-05
,
abs_tol
=
0.0
):
...
...
@@ -15,6 +16,17 @@ def allclose(a_list, b_list, rel_tol=1e-05, abs_tol=0.0):
)
def
test_slice_constructors
():
assert
m
.
make_forward_slice_size_t
()
==
slice
(
0
,
-
1
,
1
)
assert
m
.
make_reversed_slice_object
()
==
slice
(
None
,
None
,
-
1
)
@
pytest
.
mark
.
skipif
(
not
m
.
has_optional
,
reason
=
"no <optional>"
)
def
test_slice_constructors_explicit_optional
():
assert
m
.
make_reversed_slice_size_t_optional
()
==
slice
(
None
,
None
,
-
1
)
assert
m
.
make_reversed_slice_size_t_optional_verbose
()
==
slice
(
None
,
None
,
-
1
)
def
test_generalized_iterators
():
assert
list
(
m
.
IntPairs
([(
1
,
2
),
(
3
,
4
),
(
0
,
5
)]).
nonzero
())
==
[(
1
,
2
),
(
3
,
4
)]
assert
list
(
m
.
IntPairs
([(
1
,
2
),
(
2
,
0
),
(
0
,
3
),
(
4
,
5
)]).
nonzero
())
==
[(
1
,
2
)]
...
...
@@ -24,6 +36,10 @@ def test_generalized_iterators():
assert
list
(
m
.
IntPairs
([(
1
,
2
),
(
2
,
0
),
(
0
,
3
),
(
4
,
5
)]).
nonzero_keys
())
==
[
1
]
assert
list
(
m
.
IntPairs
([(
0
,
3
),
(
1
,
2
),
(
3
,
4
)]).
nonzero_keys
())
==
[]
assert
list
(
m
.
IntPairs
([(
1
,
2
),
(
3
,
4
),
(
0
,
5
)]).
nonzero_values
())
==
[
2
,
4
]
assert
list
(
m
.
IntPairs
([(
1
,
2
),
(
2
,
0
),
(
0
,
3
),
(
4
,
5
)]).
nonzero_values
())
==
[
2
]
assert
list
(
m
.
IntPairs
([(
0
,
3
),
(
1
,
2
),
(
3
,
4
)]).
nonzero_values
())
==
[]
# __next__ must continue to raise StopIteration
it
=
m
.
IntPairs
([(
0
,
0
)]).
nonzero
()
for
_
in
range
(
3
):
...
...
@@ -36,6 +52,40 @@ def test_generalized_iterators():
next
(
it
)
def
test_generalized_iterators_simple
():
assert
list
(
m
.
IntPairs
([(
1
,
2
),
(
3
,
4
),
(
0
,
5
)]).
simple_iterator
())
==
[
(
1
,
2
),
(
3
,
4
),
(
0
,
5
),
]
assert
list
(
m
.
IntPairs
([(
1
,
2
),
(
3
,
4
),
(
0
,
5
)]).
simple_keys
())
==
[
1
,
3
,
0
]
assert
list
(
m
.
IntPairs
([(
1
,
2
),
(
3
,
4
),
(
0
,
5
)]).
simple_values
())
==
[
2
,
4
,
5
]
def
test_iterator_referencing
():
"""Test that iterators reference rather than copy their referents."""
vec
=
m
.
VectorNonCopyableInt
()
vec
.
append
(
3
)
vec
.
append
(
5
)
assert
[
int
(
x
)
for
x
in
vec
]
==
[
3
,
5
]
# Increment everything to make sure the referents can be mutated
for
x
in
vec
:
x
.
set
(
int
(
x
)
+
1
)
assert
[
int
(
x
)
for
x
in
vec
]
==
[
4
,
6
]
vec
=
m
.
VectorNonCopyableIntPair
()
vec
.
append
([
3
,
4
])
vec
.
append
([
5
,
7
])
assert
[
int
(
x
)
for
x
in
vec
.
keys
()]
==
[
3
,
5
]
assert
[
int
(
x
)
for
x
in
vec
.
values
()]
==
[
4
,
7
]
for
x
in
vec
.
keys
():
x
.
set
(
int
(
x
)
+
1
)
for
x
in
vec
.
values
():
x
.
set
(
int
(
x
)
+
10
)
assert
[
int
(
x
)
for
x
in
vec
.
keys
()]
==
[
4
,
6
]
assert
[
int
(
x
)
for
x
in
vec
.
values
()]
==
[
14
,
17
]
def
test_sliceable
():
sliceable
=
m
.
Sliceable
(
100
)
assert
sliceable
[::]
==
(
0
,
100
,
1
)
...
...
@@ -139,6 +189,7 @@ def test_map_iterator():
assert
sm
[
k
]
==
expected
[
k
]
for
k
,
v
in
sm
.
items
():
assert
v
==
expected
[
k
]
assert
list
(
sm
.
values
())
==
[
expected
[
k
]
for
k
in
sm
]
it
=
iter
(
m
.
StringMap
({}))
for
_
in
range
(
3
):
# __next__ must continue to raise StopIteration
...
...
tests/test_smart_ptr.cpp
View file @
e315e1fe
...
...
@@ -24,7 +24,7 @@ template <typename T> class huge_unique_ptr {
std
::
unique_ptr
<
T
>
ptr
;
uint64_t
padding
[
10
];
public:
huge_unique_ptr
(
T
*
p
)
:
ptr
(
p
)
{}
explicit
huge_unique_ptr
(
T
*
p
)
:
ptr
(
p
)
{}
T
*
get
()
{
return
ptr
.
get
();
}
};
...
...
@@ -33,7 +33,7 @@ template <typename T>
class
custom_unique_ptr
{
std
::
unique_ptr
<
T
>
impl
;
public:
custom_unique_ptr
(
T
*
p
)
:
impl
(
p
)
{
}
explicit
custom_unique_ptr
(
T
*
p
)
:
impl
(
p
)
{}
T
*
get
()
const
{
return
impl
.
get
();
}
T
*
release_ptr
()
{
return
impl
.
release
();
}
};
...
...
@@ -46,7 +46,7 @@ class shared_ptr_with_addressof_operator {
std
::
shared_ptr
<
T
>
impl
;
public:
shared_ptr_with_addressof_operator
(
)
=
default
;
shared_ptr_with_addressof_operator
(
T
*
p
)
:
impl
(
p
)
{
}
explicit
shared_ptr_with_addressof_operator
(
T
*
p
)
:
impl
(
p
)
{}
T
*
get
()
const
{
return
impl
.
get
();
}
T
**
operator
&
()
{
throw
std
::
logic_error
(
"Call of overloaded operator& is not expected"
);
}
};
...
...
@@ -59,7 +59,7 @@ class unique_ptr_with_addressof_operator {
std
::
unique_ptr
<
T
>
impl
;
public:
unique_ptr_with_addressof_operator
()
=
default
;
unique_ptr_with_addressof_operator
(
T
*
p
)
:
impl
(
p
)
{
}
explicit
unique_ptr_with_addressof_operator
(
T
*
p
)
:
impl
(
p
)
{}
T
*
get
()
const
{
return
impl
.
get
();
}
T
*
release_ptr
()
{
return
impl
.
release
();
}
T
**
operator
&
()
{
throw
std
::
logic_error
(
"Call of overloaded operator& is not expected"
);
}
...
...
@@ -68,7 +68,7 @@ public:
// Custom object with builtin reference counting (see 'object.h' for the implementation)
class
MyObject1
:
public
Object
{
public:
MyObject1
(
int
value
)
:
value
(
value
)
{
print_created
(
this
,
toString
());
}
explicit
MyObject1
(
int
value
)
:
value
(
value
)
{
print_created
(
this
,
toString
());
}
std
::
string
toString
()
const
override
{
return
"MyObject1["
+
std
::
to_string
(
value
)
+
"]"
;
}
protected:
~
MyObject1
()
override
{
print_destroyed
(
this
);
}
...
...
@@ -80,7 +80,7 @@ private:
class
MyObject2
{
public:
MyObject2
(
const
MyObject2
&
)
=
default
;
MyObject2
(
int
value
)
:
value
(
value
)
{
print_created
(
this
,
toString
());
}
explicit
MyObject2
(
int
value
)
:
value
(
value
)
{
print_created
(
this
,
toString
());
}
std
::
string
toString
()
const
{
return
"MyObject2["
+
std
::
to_string
(
value
)
+
"]"
;
}
virtual
~
MyObject2
()
{
print_destroyed
(
this
);
}
private:
...
...
@@ -91,7 +91,7 @@ private:
class
MyObject3
:
public
std
::
enable_shared_from_this
<
MyObject3
>
{
public:
MyObject3
(
const
MyObject3
&
)
=
default
;
MyObject3
(
int
value
)
:
value
(
value
)
{
print_created
(
this
,
toString
());
}
explicit
MyObject3
(
int
value
)
:
value
(
value
)
{
print_created
(
this
,
toString
());
}
std
::
string
toString
()
const
{
return
"MyObject3["
+
std
::
to_string
(
value
)
+
"]"
;
}
virtual
~
MyObject3
()
{
print_destroyed
(
this
);
}
private:
...
...
@@ -104,7 +104,7 @@ class MyObject4;
std
::
unordered_set
<
MyObject4
*>
myobject4_instances
;
class
MyObject4
{
public:
MyObject4
(
int
value
)
:
value
{
value
}
{
explicit
MyObject4
(
int
value
)
:
value
{
value
}
{
print_created
(
this
);
myobject4_instances
.
insert
(
this
);
}
...
...
@@ -130,7 +130,7 @@ class MyObject4a;
std
::
unordered_set
<
MyObject4a
*>
myobject4a_instances
;
class
MyObject4a
{
public:
MyObject4a
(
int
i
)
{
explicit
MyObject4a
(
int
i
)
{
value
=
i
;
print_created
(
this
);
myobject4a_instances
.
insert
(
this
);
...
...
@@ -153,14 +153,14 @@ protected:
// Object derived but with public destructor and no Deleter in default holder
class
MyObject4b
:
public
MyObject4a
{
public:
MyObject4b
(
int
i
)
:
MyObject4a
(
i
)
{
print_created
(
this
);
}
explicit
MyObject4b
(
int
i
)
:
MyObject4a
(
i
)
{
print_created
(
this
);
}
~
MyObject4b
()
override
{
print_destroyed
(
this
);
}
};
// test_large_holder
class
MyObject5
{
// managed by huge_unique_ptr
public:
MyObject5
(
int
value
)
:
value
{
value
}
{
print_created
(
this
);
}
explicit
MyObject5
(
int
value
)
:
value
{
value
}
{
print_created
(
this
);
}
~
MyObject5
()
{
print_destroyed
(
this
);
}
int
value
;
};
...
...
@@ -182,6 +182,7 @@ struct SharedPtrRef {
struct
SharedFromThisRef
{
struct
B
:
std
::
enable_shared_from_this
<
B
>
{
B
()
{
print_created
(
this
);
}
// NOLINTNEXTLINE(bugprone-copy-constructor-init)
B
(
const
B
&
)
:
std
::
enable_shared_from_this
<
B
>
()
{
print_copy_created
(
this
);
}
B
(
B
&&
)
noexcept
:
std
::
enable_shared_from_this
<
B
>
()
{
print_move_created
(
this
);
}
~
B
()
{
print_destroyed
(
this
);
}
...
...
@@ -221,7 +222,7 @@ struct TypeForHolderWithAddressOf {
// test_move_only_holder_with_addressof_operator
struct
TypeForMoveOnlyHolderWithAddressOf
{
TypeForMoveOnlyHolderWithAddressOf
(
int
value
)
:
value
{
value
}
{
print_created
(
this
);
}
explicit
TypeForMoveOnlyHolderWithAddressOf
(
int
value
)
:
value
{
value
}
{
print_created
(
this
);
}
~
TypeForMoveOnlyHolderWithAddressOf
()
{
print_destroyed
(
this
);
}
std
::
string
toString
()
const
{
return
"MoveOnlyHolderWithAddressOf["
+
std
::
to_string
(
value
)
+
"]"
;
...
...
@@ -241,7 +242,7 @@ struct ElementBase {
};
struct
ElementA
:
ElementBase
{
ElementA
(
int
v
)
:
v
(
v
)
{
}
explicit
ElementA
(
int
v
)
:
v
(
v
)
{}
int
value
()
const
{
return
v
;
}
int
v
;
};
...
...
@@ -290,9 +291,9 @@ TEST_SUBMODULE(smart_ptr, m) {
py
::
implicitly_convertible
<
py
::
int_
,
MyObject1
>
();
m
.
def
(
"make_object_1"
,
[]()
->
Object
*
{
return
new
MyObject1
(
1
);
});
m
.
def
(
"make_object_2"
,
[]()
->
ref
<
Object
>
{
return
new
MyObject1
(
2
);
});
m
.
def
(
"make_object_2"
,
[]()
->
ref
<
Object
>
{
return
ref
<
Object
>
(
new
MyObject1
(
2
)
)
;
});
m
.
def
(
"make_myobject1_1"
,
[]()
->
MyObject1
*
{
return
new
MyObject1
(
4
);
});
m
.
def
(
"make_myobject1_2"
,
[]()
->
ref
<
MyObject1
>
{
return
new
MyObject1
(
5
);
});
m
.
def
(
"make_myobject1_2"
,
[]()
->
ref
<
MyObject1
>
{
return
ref
<
MyObject1
>
(
new
MyObject1
(
5
)
)
;
});
m
.
def
(
"print_object_1"
,
[](
const
Object
*
obj
)
{
py
::
print
(
obj
->
toString
());
});
m
.
def
(
"print_object_2"
,
[](
ref
<
Object
>
obj
)
{
py
::
print
(
obj
->
toString
());
});
m
.
def
(
"print_object_3"
,
[](
const
ref
<
Object
>
&
obj
)
{
py
::
print
(
obj
->
toString
());
});
...
...
@@ -327,7 +328,7 @@ TEST_SUBMODULE(smart_ptr, m) {
// test_smart_ptr_refcounting
m
.
def
(
"test_object1_refcounting"
,
[]()
{
ref
<
MyObject1
>
o
=
new
MyObject1
(
0
);
auto
o
=
ref
<
MyObject1
>
(
new
MyObject1
(
0
)
)
;
bool
good
=
o
->
getRefCount
()
==
1
;
py
::
object
o2
=
py
::
cast
(
o
,
py
::
return_value_policy
::
reference
);
// always request (partial) ownership for objects with intrusive
...
...
tests/test_stl.cpp
View file @
e315e1fe
...
...
@@ -45,7 +45,8 @@ PYBIND11_MAKE_OPAQUE(std::vector<std::string, std::allocator<std::string>>);
/// Issue #528: templated constructor
struct
TplCtorClass
{
template
<
typename
T
>
TplCtorClass
(
const
T
&
)
{
}
template
<
typename
T
>
explicit
TplCtorClass
(
const
T
&
)
{}
bool
operator
==
(
const
TplCtorClass
&
)
const
{
return
true
;
}
};
...
...
tests/test_stl.py
View file @
e315e1fe
# -*- coding: utf-8 -*-
import
pytest
from
pybind11_tests
import
ConstructorStats
,
UserType
from
pybind11_tests
import
stl
as
m
from
pybind11_tests
import
UserType
from
pybind11_tests
import
ConstructorStats
def
test_vector
(
doc
):
...
...
tests/test_stl_binders.cpp
View file @
e315e1fe
...
...
@@ -18,7 +18,7 @@
class
El
{
public:
El
()
=
delete
;
El
(
int
v
)
:
a
(
v
)
{
}
explicit
El
(
int
v
)
:
a
(
v
)
{}
int
a
;
};
...
...
tests/test_stl_binders.py
View file @
e315e1fe
...
...
@@ -2,7 +2,6 @@
import
pytest
import
env
# noqa: F401
from
pybind11_tests
import
stl_binders
as
m
...
...
@@ -161,15 +160,43 @@ def test_map_string_double():
mm
[
"b"
]
=
2.5
assert
list
(
mm
)
==
[
"a"
,
"b"
]
assert
list
(
mm
.
items
())
==
[(
"a"
,
1
),
(
"b"
,
2.5
)]
assert
str
(
mm
)
==
"MapStringDouble{a: 1, b: 2.5}"
assert
"b"
in
mm
assert
"c"
not
in
mm
assert
123
not
in
mm
# Check that keys, values, items are views, not merely iterable
keys
=
mm
.
keys
()
values
=
mm
.
values
()
items
=
mm
.
items
()
assert
list
(
keys
)
==
[
"a"
,
"b"
]
assert
len
(
keys
)
==
2
assert
"a"
in
keys
assert
"c"
not
in
keys
assert
123
not
in
keys
assert
list
(
items
)
==
[(
"a"
,
1
),
(
"b"
,
2.5
)]
assert
len
(
items
)
==
2
assert
(
"b"
,
2.5
)
in
items
assert
"hello"
not
in
items
assert
(
"b"
,
2.5
,
None
)
not
in
items
assert
list
(
values
)
==
[
1
,
2.5
]
assert
len
(
values
)
==
2
assert
1
in
values
assert
2
not
in
values
# Check that views update when the map is updated
mm
[
"c"
]
=
-
1
assert
list
(
keys
)
==
[
"a"
,
"b"
,
"c"
]
assert
list
(
values
)
==
[
1
,
2.5
,
-
1
]
assert
list
(
items
)
==
[(
"a"
,
1
),
(
"b"
,
2.5
),
(
"c"
,
-
1
)]
um
=
m
.
UnorderedMapStringDouble
()
um
[
"ua"
]
=
1.1
um
[
"ub"
]
=
2.6
assert
sorted
(
list
(
um
))
==
[
"ua"
,
"ub"
]
assert
list
(
um
.
keys
())
==
list
(
um
)
assert
sorted
(
list
(
um
.
items
()))
==
[(
"ua"
,
1.1
),
(
"ub"
,
2.6
)]
assert
list
(
zip
(
um
.
keys
(),
um
.
values
()))
==
list
(
um
.
items
())
assert
"UnorderedMapStringDouble"
in
str
(
um
)
...
...
tests/test_tagbased_polymorphic.cpp
View file @
e315e1fe
...
...
@@ -37,33 +37,35 @@ struct Animal
struct
Dog
:
Animal
{
Dog
(
const
std
::
string
&
_name
,
Kind
_kind
=
Kind
::
Dog
)
:
Animal
(
_name
,
_kind
)
{}
explicit
Dog
(
const
std
::
string
&
_name
,
Kind
_kind
=
Kind
::
Dog
)
:
Animal
(
_name
,
_kind
)
{}
std
::
string
bark
()
const
{
return
name_of_kind
(
kind
)
+
" "
+
name
+
" goes "
+
sound
;
}
std
::
string
sound
=
"WOOF!"
;
};
struct
Labrador
:
Dog
{
Labrador
(
const
std
::
string
&
_name
,
int
_excitement
=
9001
)
explicit
Labrador
(
const
std
::
string
&
_name
,
int
_excitement
=
9001
)
:
Dog
(
_name
,
Kind
::
Labrador
),
excitement
(
_excitement
)
{}
int
excitement
;
};
struct
Chihuahua
:
Dog
{
Chihuahua
(
const
std
::
string
&
_name
)
:
Dog
(
_name
,
Kind
::
Chihuahua
)
{
sound
=
"iyiyiyiyiyi"
;
}
explicit
Chihuahua
(
const
std
::
string
&
_name
)
:
Dog
(
_name
,
Kind
::
Chihuahua
)
{
sound
=
"iyiyiyiyiyi"
;
}
std
::
string
bark
()
const
{
return
Dog
::
bark
()
+
" and runs in circles"
;
}
};
struct
Cat
:
Animal
{
Cat
(
const
std
::
string
&
_name
,
Kind
_kind
=
Kind
::
Cat
)
:
Animal
(
_name
,
_kind
)
{}
explicit
Cat
(
const
std
::
string
&
_name
,
Kind
_kind
=
Kind
::
Cat
)
:
Animal
(
_name
,
_kind
)
{}
std
::
string
purr
()
const
{
return
"mrowr"
;
}
};
struct
Panther
:
Cat
{
Panther
(
const
std
::
string
&
_name
)
:
Cat
(
_name
,
Kind
::
Panther
)
{}
explicit
Panther
(
const
std
::
string
&
_name
)
:
Cat
(
_name
,
Kind
::
Panther
)
{}
std
::
string
purr
()
const
{
return
"mrrrRRRRRR"
;
}
};
...
...
@@ -86,13 +88,13 @@ std::vector<std::unique_ptr<Animal>> create_zoo()
const
std
::
type_info
*
Animal
::
type_of_kind
(
Kind
kind
)
{
switch
(
kind
)
{
case
Kind
::
Unknown
:
break
;
case
Kind
::
Unknown
:
case
Kind
::
Dog
:
break
;
case
Kind
::
Labrador
:
return
&
typeid
(
Labrador
);
case
Kind
::
Chihuahua
:
return
&
typeid
(
Chihuahua
);
case
Kind
::
LastDog
:
break
;
case
Kind
::
LastDog
:
case
Kind
::
Cat
:
break
;
case
Kind
::
Panther
:
return
&
typeid
(
Panther
);
case
Kind
::
LastCat
:
break
;
...
...
tests/test_thread.cpp
0 → 100644
View file @
e315e1fe
/*
tests/test_thread.cpp -- call pybind11 bound methods in threads
Copyright (c) 2021 Laramie Leavitt (Google LLC) <lar@google.com>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include <pybind11/cast.h>
#include <pybind11/pybind11.h>
#include <chrono>
#include <thread>
#include "pybind11_tests.h"
namespace
py
=
pybind11
;
namespace
{
struct
IntStruct
{
explicit
IntStruct
(
int
v
)
:
value
(
v
)
{};
~
IntStruct
()
{
value
=
-
value
;
}
IntStruct
(
const
IntStruct
&
)
=
default
;
IntStruct
&
operator
=
(
const
IntStruct
&
)
=
default
;
int
value
;
};
}
// namespace
TEST_SUBMODULE
(
thread
,
m
)
{
py
::
class_
<
IntStruct
>
(
m
,
"IntStruct"
).
def
(
py
::
init
([](
const
int
i
)
{
return
IntStruct
(
i
);
}));
// implicitly_convertible uses loader_life_support when an implicit
// conversion is required in order to lifetime extend the reference.
//
// This test should be run with ASAN for better effectiveness.
py
::
implicitly_convertible
<
int
,
IntStruct
>
();
m
.
def
(
"test"
,
[](
int
expected
,
const
IntStruct
&
in
)
{
{
py
::
gil_scoped_release
release
;
std
::
this_thread
::
sleep_for
(
std
::
chrono
::
milliseconds
(
5
));
}
if
(
in
.
value
!=
expected
)
{
throw
std
::
runtime_error
(
"Value changed!!"
);
}
});
m
.
def
(
"test_no_gil"
,
[](
int
expected
,
const
IntStruct
&
in
)
{
std
::
this_thread
::
sleep_for
(
std
::
chrono
::
milliseconds
(
5
));
if
(
in
.
value
!=
expected
)
{
throw
std
::
runtime_error
(
"Value changed!!"
);
}
},
py
::
call_guard
<
py
::
gil_scoped_release
>
());
// NOTE: std::string_view also uses loader_life_support to ensure that
// the string contents remain alive, but that's a C++ 17 feature.
}
tests/test_thread.py
0 → 100644
View file @
e315e1fe
# -*- coding: utf-8 -*-
import
threading
from
pybind11_tests
import
thread
as
m
class
Thread
(
threading
.
Thread
):
def
__init__
(
self
,
fn
):
super
(
Thread
,
self
).
__init__
()
self
.
fn
=
fn
self
.
e
=
None
def
run
(
self
):
try
:
for
i
in
range
(
10
):
self
.
fn
(
i
,
i
)
except
Exception
as
e
:
self
.
e
=
e
def
join
(
self
):
super
(
Thread
,
self
).
join
()
if
self
.
e
:
raise
self
.
e
def
test_implicit_conversion
():
a
=
Thread
(
m
.
test
)
b
=
Thread
(
m
.
test
)
c
=
Thread
(
m
.
test
)
for
x
in
[
a
,
b
,
c
]:
x
.
start
()
for
x
in
[
c
,
b
,
a
]:
x
.
join
()
def
test_implicit_conversion_no_gil
():
a
=
Thread
(
m
.
test_no_gil
)
b
=
Thread
(
m
.
test_no_gil
)
c
=
Thread
(
m
.
test_no_gil
)
for
x
in
[
a
,
b
,
c
]:
x
.
start
()
for
x
in
[
c
,
b
,
a
]:
x
.
join
()
tests/test_virtual_functions.cpp
View file @
e315e1fe
...
...
@@ -15,7 +15,7 @@
/* This is an example class that we'll want to be able to extend from Python */
class
ExampleVirt
{
public:
ExampleVirt
(
int
state
)
:
state
(
state
)
{
print_created
(
this
,
state
);
}
explicit
ExampleVirt
(
int
state
)
:
state
(
state
)
{
print_created
(
this
,
state
);
}
ExampleVirt
(
const
ExampleVirt
&
e
)
:
state
(
e
.
state
)
{
print_copy_created
(
this
);
}
ExampleVirt
(
ExampleVirt
&&
e
)
noexcept
:
state
(
e
.
state
)
{
print_move_created
(
this
);
...
...
@@ -454,6 +454,7 @@ template <class Base = B_Tpl>
class
PyB_Tpl
:
public
PyA_Tpl
<
Base
>
{
public:
using
PyA_Tpl
<
Base
>::
PyA_Tpl
;
// Inherit constructors (via PyA_Tpl's inherited constructors)
// NOLINTNEXTLINE(bugprone-parent-virtual-call)
int
unlucky_number
()
override
{
PYBIND11_OVERRIDE
(
int
,
Base
,
unlucky_number
,
);
}
double
lucky_number
()
override
{
PYBIND11_OVERRIDE
(
double
,
Base
,
lucky_number
,
);
}
};
...
...
tools/libsize.py
View file @
e315e1fe
# -*- coding: utf-8 -*-
from
__future__
import
print_function
,
division
from
__future__
import
division
,
print_function
import
os
import
sys
...
...
tools/make_changelog.py
View file @
e315e1fe
...
...
@@ -4,11 +4,9 @@
import
re
import
ghapi.all
from
rich
import
print
from
rich.syntax
import
Syntax
ENTRY
=
re
.
compile
(
r
"""
Suggested \s changelog \s entry:
...
...
Prev
1
…
3
4
5
6
7
8
Next
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