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
68986792
Commit
68986792
authored
Aug 30, 2017
by
Dean Moldovan
Browse files
Update enum_ and bind_vector to new-style init and pickle
Fixes #1046.
parent
4c540442
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
47 additions
and
47 deletions
+47
-47
include/pybind11/pybind11.h
include/pybind11/pybind11.h
+27
-27
include/pybind11/stl_bind.h
include/pybind11/stl_bind.h
+14
-16
tests/test_buffers.cpp
tests/test_buffers.cpp
+6
-4
No files found.
include/pybind11/pybind11.h
View file @
68986792
...
...
@@ -1313,6 +1313,30 @@ private:
}
};
/// 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
)};
};
/// Binds C++ enumerations and enumeration classes to Python
template
<
typename
Type
>
class
enum_
:
public
class_
<
Type
>
{
public:
...
...
@@ -1340,7 +1364,7 @@ public:
m
[
kv
.
first
]
=
kv
.
second
;
return
m
;
},
return_value_policy
::
copy
);
def
(
"__
init
__"
,
[](
Type
&
value
,
Scalar
i
)
{
value
=
(
Type
)
i
;
});
def
(
init
([](
Scalar
i
)
{
return
static_cast
<
Type
>
(
i
)
;
})
)
;
def
(
"__int__"
,
[](
Type
value
)
{
return
(
Scalar
)
value
;
});
#if PY_MAJOR_VERSION < 3
def
(
"__long__"
,
[](
Type
value
)
{
return
(
Scalar
)
value
;
});
...
...
@@ -1378,8 +1402,8 @@ public:
}
def
(
"__hash__"
,
[](
const
Type
&
value
)
{
return
(
Scalar
)
value
;
});
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
def
(
"__getstate__"
,
[](
const
Type
&
value
)
{
return
pybind11
::
make_tuple
((
Scalar
)
value
);
}
);
def
(
"__setstate__"
,
[](
Type
&
p
,
tuple
t
)
{
new
(
&
p
)
Type
((
Type
)
t
[
0
].
cast
<
Scalar
>
());
});
def
(
pickle
(
[](
const
Type
&
value
)
{
return
pybind11
::
make_tuple
((
Scalar
)
value
);
}
,
[](
tuple
t
)
{
return
static_cast
<
Type
>
(
t
[
0
].
cast
<
Scalar
>
());
})
)
;
}
/// Export enumeration entries into the parent scope
...
...
@@ -1402,30 +1426,6 @@ private:
handle
m_parent
;
};
/// 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
)};
};
NAMESPACE_BEGIN
(
detail
)
...
...
include/pybind11/stl_bind.h
View file @
68986792
...
...
@@ -120,17 +120,13 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
arg
(
"x"
),
"Add an item to the end of the list"
);
cl
.
def
(
"__init__"
,
[](
Vector
&
v
,
iterable
it
)
{
new
(
&
v
)
Vector
();
try
{
v
.
reserve
(
len
(
it
));
for
(
handle
h
:
it
)
v
.
push_back
(
h
.
cast
<
T
>
());
}
catch
(...)
{
v
.
~
Vector
();
throw
;
}
});
cl
.
def
(
init
([](
iterable
it
)
{
auto
v
=
std
::
unique_ptr
<
Vector
>
(
new
Vector
());
v
->
reserve
(
len
(
it
));
for
(
handle
h
:
it
)
v
->
push_back
(
h
.
cast
<
T
>
());
return
v
.
release
();
}));
cl
.
def
(
"extend"
,
[](
Vector
&
v
,
const
Vector
&
src
)
{
...
...
@@ -346,20 +342,22 @@ vector_buffer(Class_& cl) {
return
buffer_info
(
v
.
data
(),
static_cast
<
ssize_t
>
(
sizeof
(
T
)),
format_descriptor
<
T
>::
format
(),
1
,
{
v
.
size
()},
{
sizeof
(
T
)});
});
cl
.
def
(
"__
init
__"
,
[](
Vector
&
vec
,
buffer
buf
)
{
cl
.
def
(
init
([](
buffer
buf
)
{
auto
info
=
buf
.
request
();
if
(
info
.
ndim
!=
1
||
info
.
strides
[
0
]
%
static_cast
<
ssize_t
>
(
sizeof
(
T
)))
throw
type_error
(
"Only valid 1D buffers can be copied to a vector"
);
if
(
!
detail
::
compare_buffer_info
<
T
>::
compare
(
info
)
||
(
ssize_t
)
sizeof
(
T
)
!=
info
.
itemsize
)
throw
type_error
(
"Format mismatch (Python: "
+
info
.
format
+
" C++: "
+
format_descriptor
<
T
>::
format
()
+
")"
);
new
(
&
vec
)
Vector
();
vec
.
reserve
((
size_t
)
info
.
shape
[
0
]);
auto
vec
=
std
::
unique_ptr
<
Vector
>
(
new
Vector
());
vec
->
reserve
((
size_t
)
info
.
shape
[
0
]);
T
*
p
=
static_cast
<
T
*>
(
info
.
ptr
);
ssize_t
step
=
info
.
strides
[
0
]
/
static_cast
<
ssize_t
>
(
sizeof
(
T
));
T
*
end
=
p
+
info
.
shape
[
0
]
*
step
;
for
(;
p
!=
end
;
p
+=
step
)
vec
.
push_back
(
*
p
);
});
vec
->
push_back
(
*
p
);
return
vec
.
release
();
}));
return
;
}
...
...
tests/test_buffers.cpp
View file @
68986792
...
...
@@ -78,13 +78,15 @@ TEST_SUBMODULE(buffers, m) {
py
::
class_
<
Matrix
>
(
m
,
"Matrix"
,
py
::
buffer_protocol
())
.
def
(
py
::
init
<
ssize_t
,
ssize_t
>
())
/// Construct from a buffer
.
def
(
"__init__"
,
[](
Matrix
&
v
,
py
::
buffer
b
)
{
.
def
(
py
::
init
([](
py
::
buffer
b
)
{
py
::
buffer_info
info
=
b
.
request
();
if
(
info
.
format
!=
py
::
format_descriptor
<
float
>::
format
()
||
info
.
ndim
!=
2
)
throw
std
::
runtime_error
(
"Incompatible buffer format!"
);
new
(
&
v
)
Matrix
(
info
.
shape
[
0
],
info
.
shape
[
1
]);
memcpy
(
v
.
data
(),
info
.
ptr
,
sizeof
(
float
)
*
(
size_t
)
(
v
.
rows
()
*
v
.
cols
()));
})
auto
v
=
new
Matrix
(
info
.
shape
[
0
],
info
.
shape
[
1
]);
memcpy
(
v
->
data
(),
info
.
ptr
,
sizeof
(
float
)
*
(
size_t
)
(
v
->
rows
()
*
v
->
cols
()));
return
v
;
}))
.
def
(
"rows"
,
&
Matrix
::
rows
)
.
def
(
"cols"
,
&
Matrix
::
cols
)
...
...
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