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
6ebb9eaf
Commit
6ebb9eaf
authored
Jun 14, 2016
by
Wenzel Jakob
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Redesigned virtual call mechanism and user-facing syntax (breaking change!)"
This reverts commit
86d825f3
.
parent
f9502150
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
27 additions
and
103 deletions
+27
-103
docs/advanced.rst
+8
-6
example/example12.cpp
+8
-4
example/issues.cpp
+2
-32
example/issues.py
+0
-17
example/issues.ref
+0
-6
include/pybind11/attr.h
+0
-1
include/pybind11/pybind11.h
+9
-37
No files found.
docs/advanced.rst
View file @
6ebb9eaf
...
@@ -283,8 +283,9 @@ The binding code also needs a few minor adaptations (highlighted):
...
@@ -283,8 +283,9 @@ The binding code also needs a few minor adaptations (highlighted):
PYBIND11_PLUGIN(example) {
PYBIND11_PLUGIN(example) {
py::module m("example", "pybind11 example plugin");
py::module m("example", "pybind11 example plugin");
py::class_<
Animal, std::unique_ptr<Animal>, PyAnimal /* <--- trampoline*/
> animal(m, "Animal");
py::class_<
PyAnimal
> animal(m, "Animal");
animal
animal
.alias<Animal>()
.def(py::init<>())
.def(py::init<>())
.def("go", &Animal::go);
.def("go", &Animal::go);
...
@@ -296,10 +297,10 @@ The binding code also needs a few minor adaptations (highlighted):
...
@@ -296,10 +297,10 @@ The binding code also needs a few minor adaptations (highlighted):
return m.ptr();
return m.ptr();
}
}
Importantly,
pybind11 is made aware of the trampoline trampoline helper class
Importantly,
the trampoline helper class is used as the template argument to
by specifying it as the *third* template argument to :class:`class_`. The
:class:`class_`, and a call to :func:`class_::alias` informs the binding
second argument with the unique pointer is simply the default holder type used
generator that this is merely an alias for the underlying type ``Animal``.
by pybind11.
Following this, we are able to define a constructor as usual.
Following this, we are able to define a constructor as usual.
The Python session below shows how to override ``Animal::go`` and invoke it via
The Python session below shows how to override ``Animal::go`` and invoke it via
a virtual method call.
a virtual method call.
...
@@ -376,8 +377,9 @@ be realized as follows (important changes highlighted):
...
@@ -376,8 +377,9 @@ be realized as follows (important changes highlighted):
PYBIND11_PLUGIN(example) {
PYBIND11_PLUGIN(example) {
py::module m("example", "pybind11 example plugin");
py::module m("example", "pybind11 example plugin");
py::class_<
Animal, std::unique_ptr<Animal>,
PyAnimal> animal(m, "Animal");
py::class_<PyAnimal> animal(m, "Animal");
animal
animal
.alias<Animal>()
.def(py::init<>())
.def(py::init<>())
.def("go", &Animal::go);
.def("go", &Animal::go);
...
...
example/example12.cpp
View file @
6ebb9eaf
...
@@ -82,11 +82,15 @@ void runExample12Virtual(Example12 *ex) {
...
@@ -82,11 +82,15 @@ void runExample12Virtual(Example12 *ex) {
}
}
void
init_ex12
(
py
::
module
&
m
)
{
void
init_ex12
(
py
::
module
&
m
)
{
/* Important: indicate the trampoline class PyExample12 using the third
/* Important: use the wrapper type as a template
argument to py::class_. The second argument with the unique pointer
argument to class_<>, but use the original name
is simply the default holder type used by pybind11. */
to denote the type */
py
::
class_
<
Example12
,
std
::
unique_ptr
<
Example12
>
,
PyExample12
>
(
m
,
"Example12"
)
py
::
class_
<
PyExample12
>
(
m
,
"Example12"
)
/* Declare that 'PyExample12' is really an alias for the original type 'Example12' */
.
alias
<
Example12
>
()
.
def
(
py
::
init
<
int
>
())
.
def
(
py
::
init
<
int
>
())
/* Copy constructor (not needed in this case, but should generally be declared in this way) */
.
def
(
py
::
init
<
const
PyExample12
&>
())
/* Reference original class in function definitions */
/* Reference original class in function definitions */
.
def
(
"run"
,
&
Example12
::
run
)
.
def
(
"run"
,
&
Example12
::
run
)
.
def
(
"run_bool"
,
&
Example12
::
run_bool
)
.
def
(
"run_bool"
,
&
Example12
::
run_bool
)
...
...
example/issues.cpp
View file @
6ebb9eaf
...
@@ -42,7 +42,8 @@ void init_issues(py::module &m) {
...
@@ -42,7 +42,8 @@ void init_issues(py::module &m) {
}
}
};
};
py
::
class_
<
Base
,
std
::
unique_ptr
<
Base
>
,
DispatchIssue
>
(
m2
,
"DispatchIssue"
)
py
::
class_
<
DispatchIssue
>
base
(
m2
,
"DispatchIssue"
);
base
.
alias
<
Base
>
()
.
def
(
py
::
init
<>
())
.
def
(
py
::
init
<>
())
.
def
(
"dispatch"
,
&
Base
::
dispatch
);
.
def
(
"dispatch"
,
&
Base
::
dispatch
);
...
@@ -107,35 +108,4 @@ void init_issues(py::module &m) {
...
@@ -107,35 +108,4 @@ void init_issues(py::module &m) {
// (no id): don't cast doubles to ints
// (no id): don't cast doubles to ints
m2
.
def
(
"expect_float"
,
[](
float
f
)
{
return
f
;
});
m2
.
def
(
"expect_float"
,
[](
float
f
)
{
return
f
;
});
m2
.
def
(
"expect_int"
,
[](
int
i
)
{
return
i
;
});
m2
.
def
(
"expect_int"
,
[](
int
i
)
{
return
i
;
});
// (no id): don't invoke Python dispatch code when instantiating C++
// classes that were not extended on the Python side
struct
A
{
virtual
~
A
()
{}
virtual
void
f
()
{
std
::
cout
<<
"A.f()"
<<
std
::
endl
;
}
};
struct
PyA
:
A
{
PyA
()
{
std
::
cout
<<
"PyA.PyA()"
<<
std
::
endl
;
}
void
f
()
override
{
std
::
cout
<<
"PyA.f()"
<<
std
::
endl
;
PYBIND11_OVERLOAD
(
void
,
A
,
f
);
}
};
auto
call_f
=
[](
A
*
a
)
{
a
->
f
();
};
pybind11
::
class_
<
A
,
std
::
unique_ptr
<
A
>
,
PyA
>
(
m2
,
"A"
)
.
def
(
py
::
init
<>
())
.
def
(
"f"
,
&
A
::
f
);
m2
.
def
(
"call_f"
,
call_f
);
try
{
py
::
class_
<
Placeholder
>
(
m2
,
"Placeholder"
);
throw
std
::
logic_error
(
"Expected an exception!"
);
}
catch
(
std
::
runtime_error
&
)
{
/* All good */
}
}
}
example/issues.py
View file @
6ebb9eaf
...
@@ -9,7 +9,6 @@ from example.issues import Placeholder, return_vec_of_reference_wrapper
...
@@ -9,7 +9,6 @@ from example.issues import Placeholder, return_vec_of_reference_wrapper
from
example.issues
import
iterator_passthrough
from
example.issues
import
iterator_passthrough
from
example.issues
import
ElementList
,
ElementA
,
print_element
from
example.issues
import
ElementList
,
ElementA
,
print_element
from
example.issues
import
expect_float
,
expect_int
from
example.issues
import
expect_float
,
expect_int
from
example.issues
import
A
,
call_f
import
gc
import
gc
print_cchar
(
"const char *"
)
print_cchar
(
"const char *"
)
...
@@ -56,19 +55,3 @@ except Exception as e:
...
@@ -56,19 +55,3 @@ except Exception as e:
print
(
"Failed as expected: "
+
str
(
e
))
print
(
"Failed as expected: "
+
str
(
e
))
print
(
expect_float
(
12
))
print
(
expect_float
(
12
))
class
B
(
A
):
def
__init__
(
self
):
super
(
B
,
self
)
.
__init__
()
def
f
(
self
):
print
(
"In python f()"
)
print
(
"C++ version"
)
a
=
A
()
call_f
(
a
)
print
(
"Python version"
)
b
=
B
()
call_f
(
b
)
example/issues.ref
View file @
6ebb9eaf
...
@@ -12,9 +12,3 @@ Failed as expected: Incompatible function arguments. The following argument type
...
@@ -12,9 +12,3 @@ Failed as expected: Incompatible function arguments. The following argument type
1. (int) -> int
1. (int) -> int
Invoked with: 5.2
Invoked with: 5.2
12.0
12.0
C++ version
A.f()
Python version
PyA.PyA()
PyA.f()
In python f()
include/pybind11/attr.h
View file @
6ebb9eaf
...
@@ -71,7 +71,6 @@ enum op_type : int;
...
@@ -71,7 +71,6 @@ enum op_type : int;
struct
undefined_t
;
struct
undefined_t
;
template
<
op_id
id
,
op_type
ot
,
typename
L
=
undefined_t
,
typename
R
=
undefined_t
>
struct
op_
;
template
<
op_id
id
,
op_type
ot
,
typename
L
=
undefined_t
,
typename
R
=
undefined_t
>
struct
op_
;
template
<
typename
...
Args
>
struct
init
;
template
<
typename
...
Args
>
struct
init
;
template
<
typename
...
Args
>
struct
init_alias
;
inline
void
keep_alive_impl
(
int
Nurse
,
int
Patient
,
handle
args
,
handle
ret
);
inline
void
keep_alive_impl
(
int
Nurse
,
int
Patient
,
handle
args
,
handle
ret
);
/// Internal data structure which holds metadata about a keyword argument
/// Internal data structure which holds metadata about a keyword argument
...
...
include/pybind11/pybind11.h
View file @
6ebb9eaf
...
@@ -500,7 +500,7 @@ public:
...
@@ -500,7 +500,7 @@ public:
NAMESPACE_BEGIN
(
detail
)
NAMESPACE_BEGIN
(
detail
)
/// Generic support for creating new Python heap types
/// Generic support for creating new Python heap types
class
generic_type
:
public
object
{
class
generic_type
:
public
object
{
template
<
typename
type
,
typename
holder_type
,
typename
type_alias
>
friend
class
class_
;
template
<
typename
type
,
typename
holder_type
>
friend
class
class_
;
public
:
public
:
PYBIND11_OBJECT_DEFAULT
(
generic_type
,
object
,
PyType_Check
)
PYBIND11_OBJECT_DEFAULT
(
generic_type
,
object
,
PyType_Check
)
protected
:
protected
:
...
@@ -725,7 +725,7 @@ protected:
...
@@ -725,7 +725,7 @@ protected:
};
};
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
detail
)
template
<
typename
type
,
typename
holder_type
=
std
::
unique_ptr
<
type
>
,
typename
type_alias
=
type
>
template
<
typename
type
,
typename
holder_type
=
std
::
unique_ptr
<
type
>>
class
class_
:
public
detail
::
generic_type
{
class
class_
:
public
detail
::
generic_type
{
public
:
public
:
typedef
detail
::
instance
<
type
,
holder_type
>
instance_type
;
typedef
detail
::
instance
<
type
,
holder_type
>
instance_type
;
...
@@ -747,11 +747,6 @@ public:
...
@@ -747,11 +747,6 @@ public:
detail
::
process_attributes
<
Extra
...
>::
init
(
extra
...,
&
record
);
detail
::
process_attributes
<
Extra
...
>::
init
(
extra
...,
&
record
);
detail
::
generic_type
::
initialize
(
&
record
);
detail
::
generic_type
::
initialize
(
&
record
);
if
(
!
std
::
is_same
<
type
,
type_alias
>::
value
)
{
auto
&
instances
=
pybind11
::
detail
::
get_internals
().
registered_types_cpp
;
instances
[
std
::
type_index
(
typeid
(
type_alias
))]
=
instances
[
std
::
type_index
(
typeid
(
type
))];
}
}
}
template
<
typename
Func
,
typename
...
Extra
>
template
<
typename
Func
,
typename
...
Extra
>
...
@@ -789,12 +784,6 @@ public:
...
@@ -789,12 +784,6 @@ public:
return
*
this
;
return
*
this
;
}
}
template
<
typename
...
Args
,
typename
...
Extra
>
class_
&
def
(
const
detail
::
init_alias
<
Args
...
>
&
init
,
const
Extra
&
...
extra
)
{
init
.
template
execute
<
type
>
(
*
this
,
extra
...);
return
*
this
;
}
template
<
typename
Func
>
class_
&
def_buffer
(
Func
&&
func
)
{
template
<
typename
Func
>
class_
&
def_buffer
(
Func
&&
func
)
{
struct
capture
{
Func
func
;
};
struct
capture
{
Func
func
;
};
capture
*
ptr
=
new
capture
{
std
::
forward
<
Func
>
(
func
)
};
capture
*
ptr
=
new
capture
{
std
::
forward
<
Func
>
(
func
)
};
...
@@ -882,6 +871,11 @@ public:
...
@@ -882,6 +871,11 @@ public:
return
*
this
;
return
*
this
;
}
}
template
<
typename
target
>
class_
alias
()
{
auto
&
instances
=
pybind11
::
detail
::
get_internals
().
registered_types_cpp
;
instances
[
std
::
type_index
(
typeid
(
target
))]
=
instances
[
std
::
type_index
(
typeid
(
type
))];
return
*
this
;
}
private
:
private
:
/// 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
>
...
@@ -980,31 +974,9 @@ private:
...
@@ -980,31 +974,9 @@ private:
NAMESPACE_BEGIN
(
detail
)
NAMESPACE_BEGIN
(
detail
)
template
<
typename
...
Args
>
struct
init
{
template
<
typename
...
Args
>
struct
init
{
template
<
typename
Base
,
typename
Holder
,
typename
Alias
,
typename
...
Extra
,
template
<
typename
Base
,
typename
Holder
,
typename
...
Extra
>
void
execute
(
pybind11
::
class_
<
Base
,
Holder
>
&
class_
,
const
Extra
&
...
extra
)
const
{
typename
std
::
enable_if
<
std
::
is_same
<
Base
,
Alias
>::
value
,
int
>::
type
=
0
>
void
execute
(
pybind11
::
class_
<
Base
,
Holder
,
Alias
>
&
class_
,
const
Extra
&
...
extra
)
const
{
/// Function which calls a specific C++ in-place constructor
/// Function which calls a specific C++ in-place constructor
class_
.
def
(
"__init__"
,
[](
Base
*
self_
,
Args
...
args
)
{
new
(
self_
)
Base
(
args
...);
},
extra
...);
class_
.
def
(
"__init__"
,
[](
Base
*
instance
,
Args
...
args
)
{
new
(
instance
)
Base
(
args
...);
},
extra
...);
}
template
<
typename
Base
,
typename
Holder
,
typename
Alias
,
typename
...
Extra
,
typename
std
::
enable_if
<!
std
::
is_same
<
Base
,
Alias
>::
value
&&
std
::
is_constructible
<
Base
,
Args
...
>::
value
,
int
>::
type
=
0
>
void
execute
(
pybind11
::
class_
<
Base
,
Holder
,
Alias
>
&
class_
,
const
Extra
&
...
extra
)
const
{
handle
cl_type
=
class_
;
class_
.
def
(
"__init__"
,
[
cl_type
](
handle
self_
,
Args
...
args
)
{
if
(
self_
.
get_type
()
==
cl_type
)
new
(
self_
.
cast
<
Base
*>
())
Base
(
args
...);
else
new
(
self_
.
cast
<
Alias
*>
())
Alias
(
args
...);
},
extra
...);
}
template
<
typename
Base
,
typename
Holder
,
typename
Alias
,
typename
...
Extra
,
typename
std
::
enable_if
<!
std
::
is_same
<
Base
,
Alias
>::
value
&&
!
std
::
is_constructible
<
Base
,
Args
...
>::
value
,
int
>::
type
=
0
>
void
execute
(
pybind11
::
class_
<
Base
,
Holder
,
Alias
>
&
class_
,
const
Extra
&
...
extra
)
const
{
class_
.
def
(
"__init__"
,
[](
Alias
*
self
,
Args
...
args
)
{
new
(
self
)
Alias
(
args
...);
},
extra
...);
}
}
};
};
...
...
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