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
f5fae929
Commit
f5fae929
authored
Aug 24, 2015
by
Wenzel Jakob
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avoid std::string when creating signatures, and make nicer type names. binary size reduced by ~10%
parent
10d992eb
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
133 additions
and
40 deletions
+133
-40
include/pybind/cast.h
+106
-20
include/pybind/common.h
+1
-1
include/pybind/functional.h
+5
-1
include/pybind/pybind.h
+18
-16
include/pybind/stl.h
+3
-2
No files found.
include/pybind/cast.h
View file @
f5fae929
...
@@ -17,16 +17,98 @@
...
@@ -17,16 +17,98 @@
NAMESPACE_BEGIN
(
pybind
)
NAMESPACE_BEGIN
(
pybind
)
NAMESPACE_BEGIN
(
detail
)
NAMESPACE_BEGIN
(
detail
)
#if defined(_MSC_VER)
#define NOINLINE __declspec(noinline)
#else
#define NOINLINE __attribute__ ((noinline))
#endif
/** Linked list descriptor type for function signatures (produces smaller binaries
* compared to a previous solution using std::string and operator +=) */
class
descr
{
public
:
struct
entry
{
const
std
::
type_info
*
type
=
nullptr
;
const
char
*
str
=
nullptr
;
entry
*
next
=
nullptr
;
entry
(
const
std
::
type_info
*
type
)
:
type
(
type
)
{
}
entry
(
const
char
*
str
)
:
str
(
str
)
{
}
};
descr
()
{
}
descr
(
descr
&&
d
)
:
first
(
d
.
first
),
last
(
d
.
last
)
{
d
.
first
=
d
.
last
=
nullptr
;
}
NOINLINE
descr
(
const
char
*
str
)
{
first
=
last
=
new
entry
{
str
};
}
NOINLINE
descr
(
const
std
::
type_info
&
type
)
{
first
=
last
=
new
entry
{
&
type
};
}
NOINLINE
void
operator
+
(
const
char
*
str
)
{
entry
*
next
=
new
entry
{
str
};
last
->
next
=
next
;
last
=
next
;
}
NOINLINE
void
operator
+
(
const
std
::
type_info
*
type
)
{
entry
*
next
=
new
entry
{
type
};
last
->
next
=
next
;
last
=
next
;
}
NOINLINE
void
operator
+=
(
descr
&&
other
)
{
last
->
next
=
other
.
first
;
while
(
last
->
next
)
last
=
last
->
next
;
other
.
first
=
other
.
last
=
nullptr
;
}
NOINLINE
friend
descr
operator
+
(
descr
&&
l
,
descr
&&
r
)
{
descr
result
(
std
::
move
(
l
));
result
+=
std
::
move
(
r
);
return
result
;
}
NOINLINE
std
::
string
str
()
const
{
std
::
string
result
;
auto
const
&
registered_types
=
get_internals
().
registered_types
;
for
(
entry
*
it
=
first
;
it
!=
nullptr
;
it
=
it
->
next
)
{
if
(
it
->
type
)
{
auto
it2
=
registered_types
.
find
(
it
->
type
);
if
(
it2
!=
registered_types
.
end
())
{
result
+=
it2
->
second
.
type
->
tp_name
;
}
else
{
std
::
string
tname
(
it
->
type
->
name
());
detail
::
clean_type_id
(
tname
);
result
+=
tname
;
}
}
else
{
result
+=
it
->
str
;
}
}
return
result
;
}
NOINLINE
~
descr
()
{
while
(
first
)
{
entry
*
tmp
=
first
->
next
;
delete
first
;
first
=
tmp
;
}
}
entry
*
first
=
nullptr
;
entry
*
last
=
nullptr
;
};
#undef NOINLINE
/// Generic type caster for objects stored on the heap
/// Generic type caster for objects stored on the heap
template
<
typename
type
>
class
type_caster
{
template
<
typename
type
>
class
type_caster
{
public
:
public
:
typedef
instance
<
type
>
instance_type
;
typedef
instance
<
type
>
instance_type
;
static
std
::
string
name
()
{
return
type_id
<
type
>
(
);
}
static
descr
descr
()
{
return
typeid
(
type
);
}
type_caster
()
{
type_caster
()
{
auto
const
&
registered_types
=
get_internals
().
registered_types
;
auto
const
&
registered_types
=
get_internals
().
registered_types
;
auto
it
=
registered_types
.
find
(
type_id
<
type
>
(
));
auto
it
=
registered_types
.
find
(
&
typeid
(
type
));
if
(
it
!=
registered_types
.
end
())
if
(
it
!=
registered_types
.
end
())
typeinfo
=
&
it
->
second
;
typeinfo
=
&
it
->
second
;
}
}
...
@@ -70,7 +152,7 @@ public:
...
@@ -70,7 +152,7 @@ public:
Py_INCREF
(
inst
);
Py_INCREF
(
inst
);
return
inst
;
return
inst
;
}
}
auto
it
=
internals
.
registered_types
.
find
(
type_id
<
type
>
(
));
auto
it
=
internals
.
registered_types
.
find
(
&
typeid
(
type
));
if
(
it
==
internals
.
registered_types
.
end
())
{
if
(
it
==
internals
.
registered_types
.
end
())
{
std
::
string
msg
=
std
::
string
(
"Unregistered type : "
)
+
type_id
<
type
>
();
std
::
string
msg
=
std
::
string
(
"Unregistered type : "
)
+
type_id
<
type
>
();
PyErr_SetString
(
PyExc_TypeError
,
msg
.
c_str
());
PyErr_SetString
(
PyExc_TypeError
,
msg
.
c_str
());
...
@@ -129,7 +211,7 @@ protected:
...
@@ -129,7 +211,7 @@ protected:
protected: \
protected: \
type value; \
type value; \
public: \
public: \
static
std::string name
() { return py_name; } \
static
descr descr
() { return py_name; } \
static PyObject *cast(const type *src, return_value_policy policy, PyObject *parent) { \
static PyObject *cast(const type *src, return_value_policy policy, PyObject *parent) { \
return cast(*src, policy, parent); \
return cast(*src, policy, parent); \
} \
} \
...
@@ -239,7 +321,7 @@ public:
...
@@ -239,7 +321,7 @@ public:
return
PyUnicode_DecodeLatin1
(
str
,
1
,
nullptr
);
return
PyUnicode_DecodeLatin1
(
str
,
1
,
nullptr
);
}
}
static
std
::
string
name
()
{
return
"str"
;
}
static
descr
descr
()
{
return
"str"
;
}
operator
char
*
()
{
return
value
;
}
operator
char
*
()
{
return
value
;
}
operator
char
()
{
return
*
value
;
}
operator
char
()
{
return
*
value
;
}
...
@@ -272,8 +354,13 @@ public:
...
@@ -272,8 +354,13 @@ public:
return
tuple
;
return
tuple
;
}
}
static
std
::
string
name
()
{
static
descr
descr
()
{
return
"("
+
type_caster
<
T1
>::
name
()
+
", "
+
type_caster
<
T2
>::
name
()
+
")"
;
class
descr
result
(
"("
);
result
+=
std
::
move
(
type_caster
<
typename
decay
<
T1
>::
type
>::
descr
());
result
+=
", "
;
result
+=
std
::
move
(
type_caster
<
typename
decay
<
T2
>::
type
>::
descr
());
result
+=
")"
;
return
result
;
}
}
operator
type
()
{
operator
type
()
{
...
@@ -297,23 +384,22 @@ public:
...
@@ -297,23 +384,22 @@ public:
return
cast
(
src
,
policy
,
parent
,
typename
make_index_sequence
<
size
>::
type
());
return
cast
(
src
,
policy
,
parent
,
typename
make_index_sequence
<
size
>::
type
());
}
}
static
std
::
string
name
(
const
char
**
keywords
=
nullptr
,
const
char
**
values
=
nullptr
)
{
static
descr
descr
(
const
char
**
keywords
=
nullptr
,
const
char
**
values
=
nullptr
)
{
std
::
array
<
std
::
string
,
size
>
name
s
{{
std
::
array
<
class
descr
,
size
>
descr
s
{{
type_caster
<
typename
decay
<
Tuple
>::
type
>::
name
()...
type_caster
<
typename
decay
<
Tuple
>::
type
>::
descr
()...
}};
}};
std
::
string
result
(
"("
);
class
descr
result
(
"("
);
int
counter
=
0
;
for
(
int
i
=
0
;
i
<
size
;
++
i
)
{
for
(
auto
const
&
name
:
names
)
{
if
(
keywords
&&
keywords
[
i
])
{
if
(
keywords
&&
keywords
[
counter
])
{
result
+=
keywords
[
i
];
result
+=
keywords
[
counter
];
result
+=
" : "
;
result
+=
" : "
;
}
}
result
+=
name
;
result
+=
std
::
move
(
descrs
[
i
])
;
if
(
values
&&
values
[
counter
])
{
if
(
values
&&
values
[
i
])
{
result
+=
" = "
;
result
+=
" = "
;
result
+=
values
[
counter
];
result
+=
values
[
i
];
}
}
if
(
++
counter
<
size
)
if
(
i
+
1
<
size
)
result
+=
", "
;
result
+=
", "
;
}
}
result
+=
")"
;
result
+=
")"
;
...
@@ -350,7 +436,7 @@ protected:
...
@@ -350,7 +436,7 @@ protected:
std
::
array
<
bool
,
size
>
results
{{
std
::
array
<
bool
,
size
>
results
{{
(
PyTuple_GET_ITEM
(
src
,
Indices
)
!=
nullptr
?
std
::
get
<
Indices
>
(
value
).
load
(
PyTuple_GET_ITEM
(
src
,
Indices
),
convert
)
:
false
)...
(
PyTuple_GET_ITEM
(
src
,
Indices
)
!=
nullptr
?
std
::
get
<
Indices
>
(
value
).
load
(
PyTuple_GET_ITEM
(
src
,
Indices
),
convert
)
:
false
)...
}};
}};
(
void
)
convert
;
/* avoid a warning when the tuple is empty */
(
void
)
convert
;
/* avoid a warning when the tuple is empty */
for
(
bool
r
:
results
)
for
(
bool
r
:
results
)
if
(
!
r
)
if
(
!
r
)
return
false
;
return
false
;
...
...
include/pybind/common.h
View file @
f5fae929
...
@@ -139,7 +139,7 @@ struct type_info {
...
@@ -139,7 +139,7 @@ struct type_info {
/// Internal data struture used to track registered instances and types
/// Internal data struture used to track registered instances and types
struct
internals
{
struct
internals
{
std
::
unordered_map
<
std
::
string
,
type_info
>
registered_types
;
std
::
unordered_map
<
const
std
::
type_info
*
,
type_info
>
registered_types
;
std
::
unordered_map
<
void
*
,
PyObject
*>
registered_instances
;
std
::
unordered_map
<
void
*
,
PyObject
*>
registered_instances
;
};
};
...
...
include/pybind/functional.h
View file @
f5fae929
...
@@ -38,7 +38,11 @@ public:
...
@@ -38,7 +38,11 @@ public:
return
f
.
ptr
();
return
f
.
ptr
();
}
}
PYBIND_TYPE_CASTER
(
type
,
"function<"
+
type_caster
<
std
::
tuple
<
Args
...
>>::
name
()
+
" -> "
+
type_caster
<
typename
decay
<
Return
>::
type
>::
name
()
+
">"
);
PYBIND_TYPE_CASTER
(
type
,
detail
::
descr
(
"function<"
)
+
type_caster
<
std
::
tuple
<
Args
...
>>::
descr
()
+
detail
::
descr
(
" -> "
)
+
type_caster
<
typename
decay
<
Return
>::
type
>::
descr
()
+
detail
::
descr
(
">"
));
};
};
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
detail
)
...
...
include/pybind/pybind.h
View file @
f5fae929
...
@@ -189,11 +189,12 @@ public:
...
@@ -189,11 +189,12 @@ public:
std
::
array
<
const
char
*
,
N
>
kw
{},
def
{};
std
::
array
<
const
char
*
,
N
>
kw
{},
def
{};
process_extras
(((
capture
*
)
entry
->
data
)
->
extras
,
entry
,
kw
.
data
(),
def
.
data
());
process_extras
(((
capture
*
)
entry
->
data
)
->
extras
,
entry
,
kw
.
data
(),
def
.
data
());
entry
->
signature
=
cast_in
::
name
(
kw
.
data
(),
def
.
data
());
entry
->
signature
+=
" -> "
;
entry
->
signature
+=
cast_out
::
name
();
initialize
(
entry
,
sizeof
...(
Arg
));
detail
::
descr
d
=
cast_in
::
descr
(
kw
.
data
(),
def
.
data
());
d
+=
" -> "
;
d
+=
std
::
move
(
cast_out
::
descr
());
initialize
(
entry
,
d
,
sizeof
...(
Arg
));
}
}
/// Delegating helper constructor to deal with lambda functions
/// Delegating helper constructor to deal with lambda functions
...
@@ -246,11 +247,11 @@ private:
...
@@ -246,11 +247,11 @@ private:
std
::
array
<
const
char
*
,
N
>
kw
{},
def
{};
std
::
array
<
const
char
*
,
N
>
kw
{},
def
{};
process_extras
(((
capture
*
)
entry
->
data
)
->
extras
,
entry
,
kw
.
data
(),
def
.
data
());
process_extras
(((
capture
*
)
entry
->
data
)
->
extras
,
entry
,
kw
.
data
(),
def
.
data
());
entry
->
signature
=
cast_in
::
name
(
kw
.
data
(),
def
.
data
());
detail
::
descr
d
=
cast_in
::
descr
(
kw
.
data
(),
def
.
data
());
entry
->
signature
+=
" -> "
;
d
+=
" -> "
;
entry
->
signature
+=
cast_out
::
name
(
);
d
+=
std
::
move
(
cast_out
::
descr
()
);
initialize
(
entry
,
sizeof
...(
Arg
));
initialize
(
entry
,
d
,
sizeof
...(
Arg
));
}
}
static
PyObject
*
dispatcher
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
{
static
PyObject
*
dispatcher
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
{
...
@@ -322,9 +323,10 @@ private:
...
@@ -322,9 +323,10 @@ private:
}
}
}
}
void
initialize
(
function_entry
*
entry
,
int
args
)
{
void
initialize
(
function_entry
*
entry
,
const
detail
::
descr
&
descr
,
int
args
)
{
if
(
entry
->
name
==
nullptr
)
if
(
entry
->
name
==
nullptr
)
entry
->
name
=
""
;
entry
->
name
=
""
;
if
(
entry
->
keywords
!=
0
&&
entry
->
keywords
!=
args
)
if
(
entry
->
keywords
!=
0
&&
entry
->
keywords
!=
args
)
throw
std
::
runtime_error
(
throw
std
::
runtime_error
(
"cpp_function(): function
\"
"
+
std
::
string
(
entry
->
name
)
+
"
\"
takes "
+
"cpp_function(): function
\"
"
+
std
::
string
(
entry
->
name
)
+
"
\"
takes "
+
...
@@ -332,6 +334,7 @@ private:
...
@@ -332,6 +334,7 @@ private:
" pybind::arg entries were specified!"
);
" pybind::arg entries were specified!"
);
entry
->
is_constructor
=
!
strcmp
(
entry
->
name
,
"__init__"
);
entry
->
is_constructor
=
!
strcmp
(
entry
->
name
,
"__init__"
);
entry
->
signature
=
descr
.
str
();
if
(
!
entry
->
sibling
||
!
PyCFunction_Check
(
entry
->
sibling
))
{
if
(
!
entry
->
sibling
||
!
PyCFunction_Check
(
entry
->
sibling
))
{
entry
->
def
=
new
PyMethodDef
();
entry
->
def
=
new
PyMethodDef
();
...
@@ -423,7 +426,7 @@ class custom_type : public object {
...
@@ -423,7 +426,7 @@ class custom_type : public object {
public
:
public
:
PYBIND_OBJECT_DEFAULT
(
custom_type
,
object
,
PyType_Check
)
PYBIND_OBJECT_DEFAULT
(
custom_type
,
object
,
PyType_Check
)
custom_type
(
object
&
scope
,
const
char
*
name_
,
const
std
::
string
&
type_name
,
custom_type
(
object
&
scope
,
const
char
*
name_
,
const
std
::
type_info
*
tinfo
,
size_t
type_size
,
size_t
instance_size
,
size_t
type_size
,
size_t
instance_size
,
void
(
*
init_holder
)(
PyObject
*
),
const
destructor
&
dealloc
,
void
(
*
init_holder
)(
PyObject
*
),
const
destructor
&
dealloc
,
PyObject
*
parent
,
const
char
*
doc
)
{
PyObject
*
parent
,
const
char
*
doc
)
{
...
@@ -465,7 +468,7 @@ public:
...
@@ -465,7 +468,7 @@ public:
if
(((
module
&
)
scope
).
check
())
if
(((
module
&
)
scope
).
check
())
attr
(
"__module__"
)
=
scope_name
;
attr
(
"__module__"
)
=
scope_name
;
auto
&
type_info
=
detail
::
get_internals
().
registered_types
[
t
ype_name
];
auto
&
type_info
=
detail
::
get_internals
().
registered_types
[
t
info
];
type_info
.
type
=
(
PyTypeObject
*
)
m_ptr
;
type_info
.
type
=
(
PyTypeObject
*
)
m_ptr
;
type_info
.
type_size
=
type_size
;
type_info
.
type_size
=
type_size
;
type_info
.
init_holder
=
init_holder
;
type_info
.
init_holder
=
init_holder
;
...
@@ -592,13 +595,13 @@ public:
...
@@ -592,13 +595,13 @@ public:
PYBIND_OBJECT
(
class_
,
detail
::
custom_type
,
PyType_Check
)
PYBIND_OBJECT
(
class_
,
detail
::
custom_type
,
PyType_Check
)
class_
(
object
&
scope
,
const
char
*
name
,
const
char
*
doc
=
nullptr
)
class_
(
object
&
scope
,
const
char
*
name
,
const
char
*
doc
=
nullptr
)
:
detail
::
custom_type
(
scope
,
name
,
type_id
<
type
>
(
),
sizeof
(
type
),
:
detail
::
custom_type
(
scope
,
name
,
&
typeid
(
type
),
sizeof
(
type
),
sizeof
(
instance_type
),
init_holder
,
dealloc
,
sizeof
(
instance_type
),
init_holder
,
dealloc
,
nullptr
,
doc
)
{
}
nullptr
,
doc
)
{
}
class_
(
object
&
scope
,
const
char
*
name
,
object
&
parent
,
class_
(
object
&
scope
,
const
char
*
name
,
object
&
parent
,
const
char
*
doc
=
nullptr
)
const
char
*
doc
=
nullptr
)
:
detail
::
custom_type
(
scope
,
name
,
type_id
<
type
>
(
),
sizeof
(
type
),
:
detail
::
custom_type
(
scope
,
name
,
&
typeid
(
type
),
sizeof
(
type
),
sizeof
(
instance_type
),
init_holder
,
dealloc
,
sizeof
(
instance_type
),
init_holder
,
dealloc
,
parent
.
ptr
(),
doc
)
{
}
parent
.
ptr
(),
doc
)
{
}
...
@@ -790,11 +793,10 @@ template <typename InputType, typename OutputType> void implicitly_convertible()
...
@@ -790,11 +793,10 @@ template <typename InputType, typename OutputType> void implicitly_convertible()
PyErr_Clear
();
PyErr_Clear
();
return
result
;
return
result
;
};
};
std
::
string
output_type_name
=
type_id
<
OutputType
>
();
auto
&
registered_types
=
detail
::
get_internals
().
registered_types
;
auto
&
registered_types
=
detail
::
get_internals
().
registered_types
;
auto
it
=
registered_types
.
find
(
output_type_name
);
auto
it
=
registered_types
.
find
(
&
typeid
(
OutputType
)
);
if
(
it
==
registered_types
.
end
())
if
(
it
==
registered_types
.
end
())
throw
std
::
runtime_error
(
"implicitly_convertible: Unable to find type "
+
output_type_name
);
throw
std
::
runtime_error
(
"implicitly_convertible: Unable to find type "
+
type_id
<
OutputType
>
()
);
it
->
second
.
implicit_conversions
.
push_back
(
implicit_caster
);
it
->
second
.
implicit_conversions
.
push_back
(
implicit_caster
);
}
}
...
...
include/pybind/stl.h
View file @
f5fae929
...
@@ -54,7 +54,7 @@ public:
...
@@ -54,7 +54,7 @@ public:
}
}
return
list
;
return
list
;
}
}
PYBIND_TYPE_CASTER
(
type
,
"list<"
+
value_conv
::
name
()
+
">"
);
PYBIND_TYPE_CASTER
(
type
,
detail
::
descr
(
"list<"
)
+
value_conv
::
descr
()
+
detail
::
descr
(
">"
)
);
};
};
template
<
typename
Key
,
typename
Value
>
struct
type_caster
<
std
::
map
<
Key
,
Value
>>
{
template
<
typename
Key
,
typename
Value
>
struct
type_caster
<
std
::
map
<
Key
,
Value
>>
{
...
@@ -96,7 +96,8 @@ public:
...
@@ -96,7 +96,8 @@ public:
}
}
return
dict
;
return
dict
;
}
}
PYBIND_TYPE_CASTER
(
type
,
"dict<"
+
key_conv
::
name
()
+
", "
+
value_conv
::
name
()
+
">"
);
PYBIND_TYPE_CASTER
(
type
,
detail
::
descr
(
"dict<"
)
+
key_conv
::
descr
()
+
detail
::
descr
(
", "
)
+
value_conv
::
descr
()
+
detail
::
descr
(
">"
));
};
};
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
object
&
obj
)
{
os
<<
(
const
char
*
)
obj
.
str
();
return
os
;
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
object
&
obj
)
{
os
<<
(
const
char
*
)
obj
.
str
();
return
os
;
}
...
...
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