Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
ea763a57
Commit
ea763a57
authored
Sep 22, 2016
by
Dean Moldovan
Browse files
Extend tuple and list accessor interface
parent
242b146a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
49 additions
and
44 deletions
+49
-44
include/pybind11/pybind11.h
include/pybind11/pybind11.h
+1
-1
include/pybind11/pytypes.h
include/pybind11/pytypes.h
+29
-41
tests/test_python_types.cpp
tests/test_python_types.cpp
+16
-1
tests/test_python_types.py
tests/test_python_types.py
+3
-1
No files found.
include/pybind11/pybind11.h
View file @
ea763a57
...
...
@@ -1338,7 +1338,7 @@ NAMESPACE_BEGIN(detail)
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
]
=
args
[
i
].
cast
<
object
>
().
str
();
strings
[
i
]
=
args
[
i
].
str
();
}
auto
sep
=
kwargs
.
contains
(
"sep"
)
?
kwargs
[
"sep"
]
:
cast
(
" "
);
auto
line
=
sep
.
attr
(
"join"
)(
strings
);
...
...
include/pybind11/pytypes.h
View file @
ea763a57
...
...
@@ -29,10 +29,14 @@ namespace accessor_policies {
struct
obj_attr
;
struct
str_attr
;
struct
generic_item
;
struct
list_item
;
struct
tuple_item
;
}
using
obj_attr_accessor
=
accessor
<
accessor_policies
::
obj_attr
>
;
using
str_attr_accessor
=
accessor
<
accessor_policies
::
str_attr
>
;
using
item_accessor
=
accessor
<
accessor_policies
::
generic_item
>
;
using
list_accessor
=
accessor
<
accessor_policies
::
list_item
>
;
using
tuple_accessor
=
accessor
<
accessor_policies
::
tuple_item
>
;
/// Tag and check to identify a class which implements the Python object API
class
pyobject_tag
{
};
...
...
@@ -241,57 +245,41 @@ struct generic_item {
if
(
PyObject_SetItem
(
obj
.
ptr
(),
key
.
ptr
(),
val
.
ptr
())
!=
0
)
{
throw
error_already_set
();
}
}
};
NAMESPACE_END
(
accessor_policies
)
struct
list_accessor
{
public:
list_accessor
(
handle
list
,
size_t
index
)
:
list
(
list
),
index
(
index
)
{
}
void
operator
=
(
list_accessor
o
)
{
return
operator
=
(
object
(
o
));
}
struct
list_item
{
using
key_type
=
size_t
;
void
operator
=
(
const
handle
&
o
)
{
//
PyList_
S
etItem
steals a reference to 'o'
if
(
PyList_SetItem
(
list
.
ptr
(),
(
ssize_t
)
index
,
o
.
inc_ref
().
ptr
())
<
0
)
pybind11_fail
(
"Unable to assign value in Python list!"
)
;
static
object
get
(
handle
obj
,
size_t
index
)
{
PyObject
*
result
=
PyList_
G
etItem
(
obj
.
ptr
(),
static_cast
<
ssize_t
>
(
index
));
if
(
!
result
)
{
throw
error_already_set
();
}
return
{
result
,
true
}
;
}
operator
object
()
const
{
PyObject
*
result
=
PyList_
G
etItem
(
list
.
ptr
(),
(
ssize_t
)
index
);
if
(
!
result
)
pybind11_fail
(
"Unable to retrieve value from Python list!"
);
return
object
(
result
,
true
);
static
void
set
(
handle
obj
,
size_t
index
,
handle
val
)
{
//
PyList_
S
etItem
steals a reference to 'val'
if
(
PyList_SetItem
(
obj
.
ptr
(),
static_cast
<
ssize_t
>
(
index
),
val
.
inc_ref
().
ptr
())
!=
0
)
{
throw
error_already_set
(
);
}
}
template
<
typename
T
>
T
cast
()
const
{
return
operator
object
().
cast
<
T
>
();
}
private:
handle
list
;
size_t
index
;
};
struct
tuple_accessor
{
public:
tuple_accessor
(
handle
tuple
,
size_t
index
)
:
tuple
(
tuple
),
index
(
index
)
{
}
void
operator
=
(
tuple_accessor
o
)
{
return
operator
=
(
object
(
o
));
}
struct
tuple_item
{
using
key_type
=
size_t
;
void
operator
=
(
const
handle
&
o
)
{
//
PyTuple_
S
etItem
steals a referenceto 'o'
if
(
PyTuple_SetItem
(
tuple
.
ptr
(),
(
ssize_t
)
index
,
o
.
inc_ref
().
ptr
())
<
0
)
pybind11_fail
(
"Unable to assign value in Python tuple!"
)
;
static
object
get
(
handle
obj
,
size_t
index
)
{
PyObject
*
result
=
PyTuple_
G
etItem
(
obj
.
ptr
(),
static_cast
<
ssize_t
>
(
index
));
if
(
!
result
)
{
throw
error_already_set
();
}
return
{
result
,
true
}
;
}
operator
object
()
const
{
PyObject
*
result
=
PyTuple_
G
etItem
(
tuple
.
ptr
(),
(
ssize_t
)
index
);
if
(
!
result
)
pybind11_fail
(
"Unable to retrieve value from Python tuple!"
);
return
object
(
result
,
true
);
static
void
set
(
handle
obj
,
size_t
index
,
handle
val
)
{
//
PyTuple_
S
etItem
steals a reference to 'val'
if
(
PyTuple_SetItem
(
obj
.
ptr
(),
static_cast
<
ssize_t
>
(
index
),
val
.
inc_ref
().
ptr
())
!=
0
)
{
throw
error_already_set
(
);
}
}
template
<
typename
T
>
T
cast
()
const
{
return
operator
object
().
cast
<
T
>
();
}
private:
handle
tuple
;
size_t
index
;
};
NAMESPACE_END
(
accessor_policies
)
struct
dict_iterator
{
public:
...
...
@@ -647,7 +635,7 @@ public:
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate tuple object!"
);
}
size_t
size
()
const
{
return
(
size_t
)
PyTuple_Size
(
m_ptr
);
}
detail
::
tuple_accessor
operator
[](
size_t
index
)
const
{
return
detail
::
tuple_accessor
(
*
this
,
index
)
;
}
detail
::
tuple_accessor
operator
[](
size_t
index
)
const
{
return
{
*
this
,
index
}
;
}
};
class
dict
:
public
object
{
...
...
@@ -677,7 +665,7 @@ public:
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate list object!"
);
}
size_t
size
()
const
{
return
(
size_t
)
PyList_Size
(
m_ptr
);
}
detail
::
list_accessor
operator
[](
size_t
index
)
const
{
return
detail
::
list_accessor
(
*
this
,
index
)
;
}
detail
::
list_accessor
operator
[](
size_t
index
)
const
{
return
{
*
this
,
index
}
;
}
void
append
(
handle
h
)
const
{
PyList_Append
(
m_ptr
,
h
.
ptr
());
}
};
...
...
tests/test_python_types.cpp
View file @
ea763a57
...
...
@@ -60,7 +60,7 @@ public:
py
::
list
get_list
()
{
py
::
list
list
;
list
.
append
(
py
::
str
(
"value"
));
py
::
print
(
"Entry at position 0:"
,
py
::
object
(
list
[
0
])
)
;
py
::
print
(
"Entry at position 0:"
,
list
[
0
]);
list
[
0
]
=
py
::
str
(
"overwritten"
);
return
list
;
}
...
...
@@ -257,4 +257,19 @@ test_initializer python_types([](py::module &m) {
return
d
;
});
m
.
def
(
"test_tuple_accessor"
,
[](
py
::
tuple
existing_t
)
{
try
{
existing_t
[
0
]
=
py
::
cast
(
1
);
}
catch
(
const
py
::
error_already_set
&
)
{
// --> Python system error
// Only new tuples (refcount == 1) are mutable
auto
new_t
=
py
::
tuple
(
3
);
for
(
size_t
i
=
0
;
i
<
new_t
.
size
();
++
i
)
{
new_t
[
i
]
=
py
::
cast
(
i
);
}
return
new_t
;
}
return
py
::
tuple
();
});
});
tests/test_python_types.py
View file @
ea763a57
...
...
@@ -251,7 +251,7 @@ def test_dict_api():
def
test_accessors
():
from
pybind11_tests
import
test_accessor_api
from
pybind11_tests
import
test_accessor_api
,
test_tuple_accessor
class
SubTestObject
:
attr_obj
=
1
...
...
@@ -278,3 +278,5 @@ def test_accessors():
assert
d
[
"is_none"
]
is
False
assert
d
[
"operator()"
]
==
2
assert
d
[
"operator*"
]
==
7
assert
test_tuple_accessor
(
tuple
())
==
(
0
,
1
,
2
)
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