mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
avoid std::string when creating signatures, and make nicer type names. binary size reduced by ~10%
This commit is contained in:
parent
10d992eb9c
commit
f5fae929a3
@ -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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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> names {{
|
std::array<class descr, size> descrs {{
|
||||||
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:
|
|||||||
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;
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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:
|
|||||||
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:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
|||||||
" 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 {
|
|||||||
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:
|
|||||||
if (((module &) scope).check())
|
if (((module &) scope).check())
|
||||||
attr("__module__") = scope_name;
|
attr("__module__") = scope_name;
|
||||||
|
|
||||||
auto &type_info = detail::get_internals().registered_types[type_name];
|
auto &type_info = detail::get_internals().registered_types[tinfo];
|
||||||
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:
|
|||||||
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()
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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:
|
|||||||
}
|
}
|
||||||
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; }
|
||||||
|
Loading…
Reference in New Issue
Block a user