Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Olivier B.
pybind11
Commits
f5fae929
Commit
f5fae929
authored
Aug 24, 2015
by
Wenzel Jakob
Browse files
avoid std::string when creating signatures, and make nicer type names. binary size reduced by ~10%
parent
10d992eb
Changes
5
Hide whitespace changes
Inline
Side-by-side
include/pybind/cast.h
View file @
f5fae929
...
...
@@ -17,16 +17,98 @@
NAMESPACE_BEGIN
(
pybind
)
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
template
<
typename
type
>
class
type_caster
{
public:
typedef
instance
<
type
>
instance_type
;
static
std
::
string
name
()
{
return
type
_
id
<
type
>
(
);
}
static
descr
descr
()
{
return
typeid
(
type
);
}
type_caster
()
{
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
())
typeinfo
=
&
it
->
second
;
}
...
...
@@ -70,7 +152,7 @@ public:
Py_INCREF
(
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
())
{
std
::
string
msg
=
std
::
string
(
"Unregistered type : "
)
+
type_id
<
type
>
();
PyErr_SetString
(
PyExc_TypeError
,
msg
.
c_str
());
...
...
@@ -129,7 +211,7 @@ protected:
protected: \
type value; \
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) { \
return cast(*src, policy, parent); \
} \
...
...
@@ -239,7 +321,7 @@ public:
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
;
}
...
...
@@ -272,8 +354,13 @@ public:
return
tuple
;
}
static
std
::
string
name
()
{
return
"("
+
type_caster
<
T1
>::
name
()
+
", "
+
type_caster
<
T2
>::
name
()
+
")"
;
static
descr
descr
()
{
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
()
{
...
...
@@ -297,23 +384,22 @@ public:
return
cast
(
src
,
policy
,
parent
,
typename
make_index_sequence
<
size
>::
type
());
}
static
std
::
string
name
(
const
char
**
keywords
=
nullptr
,
const
char
**
values
=
nullptr
)
{
std
::
array
<
std
::
string
,
size
>
name
s
{{
type_caster
<
typename
decay
<
Tuple
>::
type
>::
name
()...
static
descr
descr
(
const
char
**
keywords
=
nullptr
,
const
char
**
values
=
nullptr
)
{
std
::
array
<
class
descr
,
size
>
descr
s
{{
type_caster
<
typename
decay
<
Tuple
>::
type
>::
descr
()...
}};
std
::
string
result
(
"("
);
int
counter
=
0
;
for
(
auto
const
&
name
:
names
)
{
if
(
keywords
&&
keywords
[
counter
])
{
result
+=
keywords
[
counter
];
class
descr
result
(
"("
);
for
(
int
i
=
0
;
i
<
size
;
++
i
)
{
if
(
keywords
&&
keywords
[
i
])
{
result
+=
keywords
[
i
];
result
+=
" : "
;
}
result
+=
name
;
if
(
values
&&
values
[
counter
])
{
result
+=
std
::
move
(
descrs
[
i
])
;
if
(
values
&&
values
[
i
])
{
result
+=
" = "
;
result
+=
values
[
counter
];
result
+=
values
[
i
];
}
if
(
++
counter
<
size
)
if
(
i
+
1
<
size
)
result
+=
", "
;
}
result
+=
")"
;
...
...
@@ -350,7 +436,7 @@ protected:
std
::
array
<
bool
,
size
>
results
{{
(
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
)
if
(
!
r
)
return
false
;
...
...
include/pybind/common.h
View file @
f5fae929
...
...
@@ -139,7 +139,7 @@ struct type_info {
/// Internal data struture used to track registered instances and types
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
;
};
...
...
include/pybind/functional.h
View file @
f5fae929
...
...
@@ -38,7 +38,11 @@ public:
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
)
...
...
include/pybind/pybind.h
View file @
f5fae929
...
...
@@ -189,11 +189,12 @@ public:
std
::
array
<
const
char
*
,
N
>
kw
{},
def
{};
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
...
...
@@ -246,11 +247,11 @@ private:
std
::
array
<
const
char
*
,
N
>
kw
{},
def
{};
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
(
);
detail
::
descr
d
=
cast_in
::
descr
(
kw
.
data
(),
def
.
data
());
d
+=
" -> "
;
d
+=
std
::
move
(
cast_out
::
descr
()
);
initialize
(
entry
,
sizeof
...(
Arg
));
initialize
(
entry
,
d
,
sizeof
...(
Arg
));
}
static
PyObject
*
dispatcher
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
{
...
...
@@ -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
)
entry
->
name
=
""
;
if
(
entry
->
keywords
!=
0
&&
entry
->
keywords
!=
args
)
throw
std
::
runtime_error
(
"cpp_function(): function
\"
"
+
std
::
string
(
entry
->
name
)
+
"
\"
takes "
+
...
...
@@ -332,6 +334,7 @@ private:
" pybind::arg entries were specified!"
);
entry
->
is_constructor
=
!
strcmp
(
entry
->
name
,
"__init__"
);
entry
->
signature
=
descr
.
str
();
if
(
!
entry
->
sibling
||
!
PyCFunction_Check
(
entry
->
sibling
))
{
entry
->
def
=
new
PyMethodDef
();
...
...
@@ -423,7 +426,7 @@ class custom_type : public object {
public:
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
,
void
(
*
init_holder
)(
PyObject
*
),
const
destructor
&
dealloc
,
PyObject
*
parent
,
const
char
*
doc
)
{
...
...
@@ -465,7 +468,7 @@ public:
if
(((
module
&
)
scope
).
check
())
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_size
=
type_size
;
type_info
.
init_holder
=
init_holder
;
...
...
@@ -592,13 +595,13 @@ public:
PYBIND_OBJECT
(
class_
,
detail
::
custom_type
,
PyType_Check
)
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
,
nullptr
,
doc
)
{
}
class_
(
object
&
scope
,
const
char
*
name
,
object
&
parent
,
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
,
parent
.
ptr
(),
doc
)
{
}
...
...
@@ -790,11 +793,10 @@ template <typename InputType, typename OutputType> void implicitly_convertible()
PyErr_Clear
();
return
result
;
};
std
::
string
output_type_name
=
type_id
<
OutputType
>
();
auto
&
registered_types
=
detail
::
get_internals
().
registered_types
;
auto
it
=
registered_types
.
find
(
o
utput
_t
ype
_name
);
auto
it
=
registered_types
.
find
(
&
typeid
(
O
utput
T
ype
)
);
if
(
it
==
registered_types
.
end
())
throw
std
::
runtime_error
(
"implicitly_convertible: Unable to find type "
+
o
utput
_t
ype
_name
);
throw
std
::
runtime_error
(
"implicitly_convertible: Unable to find type "
+
type_id
<
O
utput
T
ype
>
()
);
it
->
second
.
implicit_conversions
.
push_back
(
implicit_caster
);
}
...
...
include/pybind/stl.h
View file @
f5fae929
...
...
@@ -54,7 +54,7 @@ public:
}
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
>>
{
...
...
@@ -96,7 +96,8 @@ public:
}
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
;
}
...
...
Write
Preview
Supports
Markdown
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