Skip to content

Commit

Permalink
add constructor annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
lyskov committed Nov 6, 2024
1 parent e0306de commit b1d1cb5
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
2 changes: 1 addition & 1 deletion documentation/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ files. Typically the following files will be generated: ``<root-module>.cpp``, `


``--annotate-includes`` [debug] if specified Binder will comment each include with type name which trigger it inclusion.
``--annotate-functions`` [debug] if specified Binder will generate an extra comment for each function/constructor bound containing its C++ type signature.


``--trace`` [debug] if specified instruct Binder to add extra debug output before binding each type. This might be useful when debugging generated code that produce seg-faults during python import.
Expand Down Expand Up @@ -253,4 +254,3 @@ Config file directives:
.. code-block:: bash
+pybind11_include_file pybind11/smart_holder.h
40 changes: 31 additions & 9 deletions source/class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,10 +1023,9 @@ string bind_constructor(ConstructorBindingInfo const &CBI, uint args_to_bind, bo
if( O_annotate_functions ) {
clang::FunctionDecl const *F = CBI.T;
string const include = relevant_include(F);
c += "\t// function-signature: " + function_qualified_name(F) + "(" + function_arguments(F) + ") file:" + (include.size() ? include.substr(1, include.size() - 2) : "") + " line:" + line_number(F) + "\n";
c += "\t// function-signature: " + function_qualified_name(F, true) + "(" + function_arguments(F) + ") file:" + (include.size() ? include.substr(1, include.size() - 2) : "") + " line:" + line_number(F) + "\n";
}


if( args_to_bind == CBI.T->getNumParams() and not CBI.T->isVariadic() ) {
c += "\tcl.def( pybind11::init<{}>()"_format(function_arguments(CBI.T));

Expand Down Expand Up @@ -1064,20 +1063,40 @@ string bind_constructor(ConstructorBindingInfo const &CBI, uint args_to_bind, bo
/// Generate code for binding default constructor
string bind_default_constructor(ConstructorBindingInfo const &CBI) // CXXRecordDecl const *, string const & binding_qualified_name)
{
string code;
if( O_annotate_functions ) {
clang::FunctionDecl const *F = CBI.T;
if(F) {
string const include = relevant_include(F);
code += "\t// function-signature: " + function_qualified_name(F, true) + "(" + function_arguments(F) + ") file:" + (include.size() ? include.substr(1, include.size() - 2) : "") + " line:" + line_number(F) + "\n";
}
else {
code += "\t// function-signature: " + CBI.class_qualified_name + "()\n";
}
}

// version before error: chosen constructor is explicit in copy-initialization
// return "\tcl.def(pybind11::init<>());__\n";

// return "\tcl.def( pybind11::init( [](){{ return new {0}(); }} ) );\n"_format(binding_qualified_name);

if( CBI.C->isAbstract() ) return "\tcl.def( pybind11::init( [](){{ return new {0}(); }} ) );\n"_format(CBI.trampoline_qualified_name);
else if( CBI.trampoline ) return "\tcl.def( pybind11::init( [](){{ return new {0}(); }}, [](){{ return new {1}(); }} ) );\n"_format(CBI.class_qualified_name, CBI.trampoline_qualified_name);
else return "\tcl.def( pybind11::init( [](){{ return new {0}(); }} ) );\n"_format(CBI.class_qualified_name);
if( CBI.C->isAbstract() ) code += "\tcl.def( pybind11::init( [](){{ return new {0}(); }} ) );\n"_format(CBI.trampoline_qualified_name);
else if( CBI.trampoline ) code += "\tcl.def( pybind11::init( [](){{ return new {0}(); }}, [](){{ return new {1}(); }} ) );\n"_format(CBI.class_qualified_name, CBI.trampoline_qualified_name);
else code += "\tcl.def( pybind11::init( [](){{ return new {0}(); }} ) );\n"_format(CBI.class_qualified_name);

return code;
}

/// Generate copy constructor in most cases this will be just: "\tcl.def(pybind11::init<{} const &>());\n"_format(binding_qualified_name);
/// but for POD structs with zero data mambers this will be a lambda function. This is done as a workaround for Pybind11 2,2+ bug
string bind_copy_constructor(ConstructorBindingInfo const &CBI) // CXXConstructorDecl const *T, string const & binding_qualified_name)
{
string code;
if( O_annotate_functions ) {
clang::FunctionDecl const *F = CBI.T;
string const include = relevant_include(F);
code += "\t// function-signature: " + function_qualified_name(F, true) + "(" + function_arguments(F) + ") file:" + (include.size() ? include.substr(1, include.size() - 2) : "") + " line:" + line_number(F) + "\n";
}
// CXXRecordDecl const *C = T->getParent();

// C->dump();
Expand Down Expand Up @@ -1106,15 +1125,18 @@ string bind_copy_constructor(ConstructorBindingInfo const &CBI) // CXXConstructo
}

if( CBI.trampoline ) {
if( CBI.C->isAbstract() ) return "\tcl.def(pybind11::init<{}{} &>());\n"_format(CBI.trampoline_qualified_name, const_bit);
if( CBI.C->isAbstract() ) code += "\tcl.def(pybind11::init<{}{} &>());\n"_format(CBI.trampoline_qualified_name, const_bit);
else {
// not yet supported by Pybind11? return "\tcl.def( pybind11::init( []({0} const &o){{ return new {0}(o); }}, []({1} const &o){{ return new {1}(o); }} )
// );\n"_format(CBI.class_qualified_name, CBI.binding_qualified_name);
return "\tcl.def( pybind11::init( []({0}{1} &o){{ return new {0}(o); }} ) );\n"_format(CBI.trampoline_qualified_name, const_bit) +
(CBI.T->getAccess() == AS_public ? "\tcl.def( pybind11::init( []({0}{1} &o){{ return new {0}(o); }} ) );\n"_format(CBI.class_qualified_name, const_bit) : "");
code += \
"\tcl.def( pybind11::init( []({0}{1} &o){{ return new {0}(o); }} ) );\n"_format(CBI.trampoline_qualified_name, const_bit) +
(CBI.T->getAccess() == AS_public ? "\tcl.def( pybind11::init( []({0}{1} &o){{ return new {0}(o); }} ) );\n"_format(CBI.class_qualified_name, const_bit) : "");
}
}
else return "\tcl.def( pybind11::init( []({0}{1} &o){{ return new {0}(o); }} ) );\n"_format(CBI.class_qualified_name, const_bit);
else code += "\tcl.def( pybind11::init( []({0}{1} &o){{ return new {0}(o); }} ) );\n"_format(CBI.class_qualified_name, const_bit);

return code;
}

// Generate binding for given constructor. If constructor have default arguments generate set of bindings by creating separate bindings for each argument with default.
Expand Down

0 comments on commit b1d1cb5

Please sign in to comment.