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
eda978e0
Commit
eda978e0
authored
Mar 15, 2016
by
Wenzel Jakob
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support for opaque types
parent
a3e34f4a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
120 additions
and
1 deletions
+120
-1
CMakeLists.txt
+1
-0
docs/advanced.rst
+53
-1
example/example.cpp
+2
-0
example/example14.cpp
+29
-0
example/example14.py
+14
-0
example/example14.ref
+6
-0
include/pybind11/cast.h
+15
-0
No files found.
CMakeLists.txt
View file @
eda978e0
...
@@ -119,6 +119,7 @@ set(PYBIND11_EXAMPLES
...
@@ -119,6 +119,7 @@ set(PYBIND11_EXAMPLES
example/example11.cpp
example/example11.cpp
example/example12.cpp
example/example12.cpp
example/example13.cpp
example/example13.cpp
example/example14.cpp
example/issues.cpp
example/issues.cpp
)
)
...
...
docs/advanced.rst
View file @
eda978e0
...
@@ -1021,7 +1021,7 @@ Partitioning code over multiple extension modules
...
@@ -1021,7 +1021,7 @@ Partitioning code over multiple extension modules
It's straightforward to split binding code over multiple extension modules, while
It's straightforward to split binding code over multiple extension modules, while
referencing types that are declared elsewhere. Everything "just" works without any special
referencing types that are declared elsewhere. Everything "just" works without any special
precautions. One exception to this rule occurs when
wanting to extend
a type declared
precautions. One exception to this rule occurs when
extending
a type declared
in another extension module. Recall the basic example from Section
in another extension module. Recall the basic example from Section
:ref:`inheritance`.
:ref:`inheritance`.
...
@@ -1063,3 +1063,55 @@ Naturally, both methods will fail when there are cyclic dependencies.
...
@@ -1063,3 +1063,55 @@ Naturally, both methods will fail when there are cyclic dependencies.
py::class_<Dog>(m, "Dog", py::base<Pet>())
py::class_<Dog>(m, "Dog", py::base<Pet>())
.def(py::init<const std::string &>())
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
.def("bark", &Dog::bark);
Treating STL data structures as opaque objects
==============================================
pybind11 heavily relies on a template matching mechanism to convert parameters
and return values that are constructed from STL data types such as vectors,
linked lists, hash tables, etc. This even works in a recursive manner, for
instance to deal with lists of hash maps of pairs of elementary and custom
types, etc.
The fundamental limitation of this approach is the internal conversion between
Python and C++ types involves a copy operation that prevents pass-by-reference
semantics. What does this mean?
Suppose we bind the following function
.. code-block:: cpp
void append_1(std::vector<int> &v) {
v.push_back(1);
}
and call it as follows from Python:
.. code-block:: python
>>> v = [5, 6]
>>> append_1(v)
>>> print(v)
[5, 6]
As you can see, when passing STL data structures by reference, modifications
are not propagated back the Python side. To deal with situations where this
desirable, pybind11 contains a simple template wrapper class named ``opaque<T>``.
``opaque<T>`` disables the underlying template machinery for
``T`` and can be used to treat STL types as opaque objects, whose contents are
never inspected or extracted (thus, they can be passed by reference).
The downside of this approach is that it the binding code becomes a bit more
wordy. The above function can be bound using the following wrapper code:
.. code-block:: cpp
m.def("append_1", [](py::opaque<std::vector<int>> &v) { append_1(v); });
Opaque types must also have a dedicated ``class_`` declaration to define a
set of admissible operations.
.. seealso::
The file :file:`example/example14.cpp` contains a complete example that
demonstrates how to create opaque types using pybind11 in more detail.
example/example.cpp
View file @
eda978e0
...
@@ -22,6 +22,7 @@ void init_ex10(py::module &);
...
@@ -22,6 +22,7 @@ void init_ex10(py::module &);
void
init_ex11
(
py
::
module
&
);
void
init_ex11
(
py
::
module
&
);
void
init_ex12
(
py
::
module
&
);
void
init_ex12
(
py
::
module
&
);
void
init_ex13
(
py
::
module
&
);
void
init_ex13
(
py
::
module
&
);
void
init_ex14
(
py
::
module
&
);
void
init_issues
(
py
::
module
&
);
void
init_issues
(
py
::
module
&
);
PYBIND11_PLUGIN
(
example
)
{
PYBIND11_PLUGIN
(
example
)
{
...
@@ -40,6 +41,7 @@ PYBIND11_PLUGIN(example) {
...
@@ -40,6 +41,7 @@ PYBIND11_PLUGIN(example) {
init_ex11
(
m
);
init_ex11
(
m
);
init_ex12
(
m
);
init_ex12
(
m
);
init_ex13
(
m
);
init_ex13
(
m
);
init_ex14
(
m
);
init_issues
(
m
);
init_issues
(
m
);
return
m
.
ptr
();
return
m
.
ptr
();
...
...
example/example14.cpp
0 → 100644
View file @
eda978e0
/*
example/example14.cpp -- opaque types
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
#include <pybind11/stl.h>
#include <vector>
typedef
std
::
vector
<
std
::
string
>
StringList
;
void
init_ex14
(
py
::
module
&
m
)
{
py
::
class_
<
py
::
opaque
<
StringList
>>
(
m
,
"StringList"
)
.
def
(
py
::
init
<>
())
.
def
(
"push_back"
,
[](
py
::
opaque
<
StringList
>
&
l
,
const
std
::
string
&
str
)
{
l
->
push_back
(
str
);
})
.
def
(
"pop_back"
,
[](
py
::
opaque
<
StringList
>
&
l
)
{
l
->
pop_back
();
})
.
def
(
"back"
,
[](
py
::
opaque
<
StringList
>
&
l
)
{
return
l
->
back
();
});
m
.
def
(
"print_opaque_list"
,
[](
py
::
opaque
<
StringList
>
&
_l
)
{
StringList
&
l
=
_l
;
std
::
cout
<<
"Opaque list: "
<<
std
::
endl
;
for
(
auto
entry
:
l
)
std
::
cout
<<
" "
<<
entry
<<
std
::
endl
;
});
}
example/example14.py
0 → 100644
View file @
eda978e0
from
__future__
import
print_function
import
sys
sys
.
path
.
append
(
'.'
)
from
example
import
StringList
,
print_opaque_list
l
=
StringList
()
l
.
push_back
(
"Element 1"
)
l
.
push_back
(
"Element 2"
)
print_opaque_list
(
l
)
print
(
"Back element is
%
s"
%
l
.
back
())
l
.
pop_back
()
print_opaque_list
(
l
)
example/example14.ref
0 → 100644
View file @
eda978e0
Opaque list:
Element 1
Element 2
Back element is Element 2
Opaque list:
Element 1
include/pybind11/cast.h
View file @
eda978e0
...
@@ -17,6 +17,21 @@
...
@@ -17,6 +17,21 @@
#include <limits>
#include <limits>
NAMESPACE_BEGIN
(
pybind11
)
NAMESPACE_BEGIN
(
pybind11
)
/// Thin wrapper type used to treat certain data types as opaque (e.g. STL vectors, etc.)
template
<
typename
Type
>
class
opaque
{
public
:
template
<
typename
...
Args
>
opaque
(
Args
&&
...
args
)
:
value
(
std
::
forward
<
Args
>
(
args
)...)
{
}
operator
Type
&
()
{
return
value
;
}
operator
const
Type
&
()
const
{
return
value
;
}
operator
Type
*
()
{
return
&
value
;
}
operator
const
Type
*
()
const
{
return
&
value
;
}
Type
*
operator
->
()
{
return
&
value
;
}
const
Type
*
operator
->
()
const
{
return
&
value
;
}
private
:
Type
value
;
};
NAMESPACE_BEGIN
(
detail
)
NAMESPACE_BEGIN
(
detail
)
/// Additional type information which does not fit into the PyTypeObject
/// Additional type information which does not fit into the PyTypeObject
...
...
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