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
5984baaf
Commit
5984baaf
authored
May 10, 2016
by
Wenzel Jakob
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
redesigned cpp_function constructor; significant space savings
parent
07ef518b
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
38 additions
and
74 deletions
+38
-74
include/pybind11/attr.h
+2
-2
include/pybind11/pybind11.h
+36
-72
No files found.
include/pybind11/attr.h
View file @
5984baaf
...
...
@@ -95,10 +95,10 @@ struct function_record {
handle
(
*
impl
)
(
function_record
*
,
handle
,
handle
)
=
nullptr
;
/// Storage for the wrapped function pointer and captured data, if any
void
*
data
=
nullptr
;
void
*
data
[
3
]
=
{
}
;
/// Pointer to custom destructor for 'data' (if needed)
void
(
*
free_data
)
(
voi
d
*
ptr
)
=
nullptr
;
void
(
*
free_data
)
(
function_recor
d
*
ptr
)
=
nullptr
;
/// Return value policy associated with this function
return_value_policy
policy
=
return_value_policy
::
automatic
;
...
...
include/pybind11/pybind11.h
View file @
5984baaf
...
...
@@ -33,77 +33,32 @@ NAMESPACE_BEGIN(pybind11)
/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
class
cpp_function
:
public
function
{
protected
:
/// Picks a suitable return value converter from cast.h
template
<
typename
T
>
using
return_value_caster
=
detail
::
type_caster
<
typename
std
::
conditional
<
std
::
is_void
<
T
>::
value
,
detail
::
void_type
,
typename
detail
::
intrinsic_type
<
T
>::
type
>::
type
>
;
/// Picks a suitable argument value converter from cast.h
template
<
typename
...
T
>
using
arg_value_caster
=
detail
::
type_caster
<
typename
std
::
tuple
<
T
...
>>
;
public
:
cpp_function
()
{
}
///
Vanilla function pointers
///
Construct a cpp_function from a vanilla function pointer
template
<
typename
Return
,
typename
...
Args
,
typename
...
Extra
>
cpp_function
(
Return
(
*
f
)(
Args
...),
const
Extra
&
...
extra
)
{
auto
rec
=
new
detail
::
function_record
();
rec
->
data
=
(
void
*
)
f
;
typedef
arg_value_caster
<
Args
...
>
cast_in
;
typedef
return_value_caster
<
Return
>
cast_out
;
/* Dispatch code which converts function arguments and performs the actual function call */
rec
->
impl
=
[](
detail
::
function_record
*
rec
,
handle
pyArgs
,
handle
parent
)
->
handle
{
cast_in
args
;
/* Try to cast the function arguments into the C++ domain */
if
(
!
args
.
load
(
pyArgs
,
true
))
return
PYBIND11_TRY_NEXT_OVERLOAD
;
/* Invoke call policy pre-call hook */
detail
::
process_attributes
<
Extra
...
>::
precall
(
pyArgs
);
/* Do the call and convert the return value back into the Python domain */
handle
result
=
cast_out
::
cast
(
args
.
template
call
<
Return
>
((
Return
(
*
)
(
Args
...))
rec
->
data
),
rec
->
policy
,
parent
);
/* Invoke call policy post-call hook */
detail
::
process_attributes
<
Extra
...
>::
postcall
(
pyArgs
,
result
);
return
result
;
};
/* Process any user-provided function attributes */
detail
::
process_attributes
<
Extra
...
>::
init
(
extra
...,
rec
);
/* Generate a readable signature describing the function's arguments and return value types */
using
detail
::
descr
;
PYBIND11_DESCR
signature
=
cast_in
::
name
()
+
detail
::
_
(
" -> "
)
+
cast_out
::
name
();
/* Register the function with Python from generic (non-templated) code */
initialize
(
rec
,
signature
.
text
(),
signature
.
types
(),
sizeof
...(
Args
));
initialize
(
f
,
f
,
extra
...);
}
///
Delegating helper constructor to deal with lambda functions
///
Construct a cpp_function from a lambda function (possibly with internal state)
template
<
typename
Func
,
typename
...
Extra
>
cpp_function
(
Func
&&
f
,
const
Extra
&
...
extra
)
{
initialize
(
std
::
forward
<
Func
>
(
f
),
(
typename
detail
::
remove_class
<
decltype
(
&
std
::
remove_reference
<
Func
>::
type
::
operator
())
>::
type
*
)
nullptr
,
extra
...);
}
///
Delegating helper constructor to deal with class methods
(non-const)
template
<
typename
Return
,
typename
Class
,
typename
...
Arg
,
typename
...
Extra
>
cpp_function
(
Return
(
Class
::*
f
)(
Arg
...),
const
Extra
&
...
extra
)
{
///
Construct a cpp_function from a class method
(non-const)
template
<
typename
Return
,
typename
Class
,
typename
...
Arg
,
typename
...
Extra
>
cpp_function
(
Return
(
Class
::*
f
)(
Arg
...),
const
Extra
&
...
extra
)
{
initialize
([
f
](
Class
*
c
,
Arg
...
args
)
->
Return
{
return
(
c
->*
f
)(
args
...);
},
(
Return
(
*
)
(
Class
*
,
Arg
...))
nullptr
,
extra
...);
}
///
Delegating helper constructor to deal with class methods
(const)
template
<
typename
Return
,
typename
Class
,
typename
...
Arg
,
typename
...
Extra
>
cpp_function
(
Return
(
Class
::*
f
)(
Arg
...)
const
,
const
Extra
&
...
extra
)
{
///
Construct a cpp_function from a class method
(const)
template
<
typename
Return
,
typename
Class
,
typename
...
Arg
,
typename
...
Extra
>
cpp_function
(
Return
(
Class
::*
f
)(
Arg
...)
const
,
const
Extra
&
...
extra
)
{
initialize
([
f
](
const
Class
*
c
,
Arg
...
args
)
->
Return
{
return
(
c
->*
f
)(
args
...);
},
(
Return
(
*
)(
const
Class
*
,
Arg
...))
nullptr
,
extra
...);
}
...
...
@@ -119,35 +74,44 @@ protected:
/* Store the function including any extra state it might have (e.g. a lambda capture object) */
auto
rec
=
new
detail
::
function_record
();
rec
->
data
=
new
capture
{
std
::
forward
<
Func
>
(
f
)
};
/* Create a cleanup handler, but only if we have to (less generated code) */
/* Store the capture object directly in the function record if there is enough space */
if
(
sizeof
(
capture
)
<=
sizeof
(
rec
->
data
))
{
new
((
capture
*
)
&
rec
->
data
)
capture
{
std
::
forward
<
Func
>
(
f
)
};
if
(
!
std
::
is_trivially_destructible
<
Func
>::
value
)
rec
->
free_data
=
[](
void
*
ptr
)
{
delete
(
capture
*
)
ptr
;
};
else
rec
->
free_data
=
operator
delete
;
rec
->
free_data
=
[](
detail
::
function_record
*
r
)
{
((
capture
*
)
&
r
->
data
)
->~
capture
();
};
}
else
{
rec
->
data
[
0
]
=
new
capture
{
std
::
forward
<
Func
>
(
f
)
};
rec
->
free_data
=
[](
detail
::
function_record
*
r
)
{
delete
((
capture
*
)
r
->
data
[
0
]);
};
}
typedef
arg_value_caster
<
Args
...
>
cast_in
;
typedef
return_value_caster
<
Return
>
cast_out
;
/* Type casters for the function arguments and return value */
typedef
detail
::
type_caster
<
typename
std
::
tuple
<
Args
...
>>
cast_in
;
typedef
detail
::
type_caster
<
typename
std
::
conditional
<
std
::
is_void
<
Return
>::
value
,
detail
::
void_type
,
typename
detail
::
intrinsic_type
<
Return
>::
type
>::
type
>
cast_out
;
/* Dispatch code which converts function arguments and performs the actual function call */
rec
->
impl
=
[](
detail
::
function_record
*
rec
,
handle
pyA
rgs
,
handle
parent
)
->
handle
{
cast_in
args
;
rec
->
impl
=
[](
detail
::
function_record
*
rec
,
handle
a
rgs
,
handle
parent
)
->
handle
{
cast_in
args
_converter
;
/* Try to cast the function arguments into the C++ domain */
if
(
!
args
.
load
(
pyA
rgs
,
true
))
if
(
!
args
_converter
.
load
(
a
rgs
,
true
))
return
PYBIND11_TRY_NEXT_OVERLOAD
;
/* Invoke call policy pre-call hook */
detail
::
process_attributes
<
Extra
...
>::
precall
(
pyArgs
);
detail
::
process_attributes
<
Extra
...
>::
precall
(
args
);
/* Get a pointer to the capture object */
capture
*
cap
=
(
capture
*
)
(
sizeof
(
capture
)
<=
sizeof
(
rec
->
data
)
?
&
rec
->
data
:
rec
->
data
[
0
]);
/* Do the call and convert the return value back into the Python domain */
handle
result
=
cast_out
::
cast
(
args
.
template
call
<
Return
>
(((
capture
*
)
rec
->
data
)
->
f
),
/* Perform the functionc all */
handle
result
=
cast_out
::
cast
(
args_converter
.
template
call
<
Return
>
(
cap
->
f
),
rec
->
policy
,
parent
);
/* Invoke call policy post-call hook */
detail
::
process_attributes
<
Extra
...
>::
postcall
(
pyA
rgs
,
result
);
detail
::
process_attributes
<
Extra
...
>::
postcall
(
a
rgs
,
result
);
return
result
;
};
...
...
@@ -160,11 +124,11 @@ protected:
PYBIND11_DESCR
signature
=
cast_in
::
name
()
+
detail
::
_
(
" -> "
)
+
cast_out
::
name
();
/* Register the function with Python from generic (non-templated) code */
initialize
(
rec
,
signature
.
text
(),
signature
.
types
(),
sizeof
...(
Args
));
initialize
_generic
(
rec
,
signature
.
text
(),
signature
.
types
(),
sizeof
...(
Args
));
}
/// Register a function call with Python (generic non-templated code goes here)
void
initialize
(
detail
::
function_record
*
rec
,
const
char
*
text
,
void
initialize
_generic
(
detail
::
function_record
*
rec
,
const
char
*
text
,
const
std
::
type_info
*
const
*
types
,
int
args
)
{
/* Create copies of all referenced C-style strings */
...
...
@@ -336,7 +300,7 @@ protected:
while
(
rec
)
{
detail
::
function_record
*
next
=
rec
->
next
;
if
(
rec
->
free_data
)
rec
->
free_data
(
rec
->
data
);
rec
->
free_data
(
rec
);
std
::
free
((
char
*
)
rec
->
name
);
std
::
free
((
char
*
)
rec
->
doc
);
std
::
free
((
char
*
)
rec
->
signature
);
...
...
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