diff --git a/CMakeLists.txt b/CMakeLists.txt index f90ff59c..888927ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0) PROJECT(binder CXX C) SET(VERSION 1.0.0) option(STATIC "Statically compile Binder. See `documentation/install.rst` for more information." OFF) -#This actually will work even with C++11 -set(CMAKE_CXX_STANDARD 14) set(CMAKE_VERBOSE_MAKEFILE ON) #So far there are exceptions in config.cpp set(LLVM_REQUIRES_EH ON) @@ -29,7 +27,7 @@ MESSAGE(STATUS "binder: Using CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH} to search find_package(Clang CONFIG QUIET PATHS /usr/lib64/cmake/clang /usr/lib/cmake/clang /usr/share/clang/cmake ) find_package(LLVM CONFIG QUIET PATHS /usr/lib64/cmake/clang /usr/lib/cmake/llvm /usr/share/llvm/cmake ) if (Clang_FOUND AND LLVM_FOUND AND NOT LLVMCONFIG ) - set(CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR};${CMAKE_MODULE_PATH}") + set(CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR};${CMAKE_MODULE_PATH}") MESSAGE(STATUS "binder: cmake configurations llvm and clang were found. LLVM_CMAKE_DIR=${LLVM_CMAKE_DIR}") include(AddLLVM) include(LLVMConfig) @@ -113,6 +111,12 @@ MESSAGE(STATUS "binder: LibClang_INCLUDE_DIR, the location of headers is ${LibC MESSAGE(STATUS "binder: LLVM_VERSION_MAJOR=${LLVM_VERSION_MAJOR}") MESSAGE(STATUS "binder: LLVM_VERSION_MINOR=${LLVM_VERSION_MINOR}") MESSAGE(STATUS "binder: LLVM_VERSION_PATCH=${LLVM_VERSION_PATCH}") +if( ${LLVM_VERSION_MAJOR} GREATER_EQUAL 16 ) +# LLVM 16 introduces the use of C++ features from C++17 +set(CMAKE_CXX_STANDARD 17) +else() +set(CMAKE_CXX_STANDARD 14) +endif() macro(add_clang_executable name) add_executable( ${name} ${ARGN} ) # set_target_properties(${name} PROPERTIES FOLDER "Clang executables") @@ -126,7 +130,7 @@ endmacro(add_clang_executable) include_directories(source) add_subdirectory(source) if (BINDER_ENABLE_TEST) - if(${CMAKE_VERSION} VERSION_LESS "3.0.0") + if(${CMAKE_VERSION} VERSION_LESS "3.0.0") message("You are running cmake version ${CMAKE_VERSION}.") message("The testing suite will be disabled as it requires cmake 3.0.0 or higher.") else() diff --git a/build-and-run-tests.py b/build-and-run-tests.py index 9cfa34e6..918bbabf 100755 --- a/build-and-run-tests.py +++ b/build-and-run-tests.py @@ -42,7 +42,7 @@ def main(args): source_path = os.path.abspath('.') - if not Options.binder: Options.binder = build.install_llvm_tool('binder', source_path+'/source', source_path + '/build', Options.binder_debug, jobs=Options.jobs, gcc_install_prefix=Options.gcc_install_prefix) + if not Options.binder: Options.binder = build.install_llvm_tool('binder', source_path+'/source', source_path + '/build', Options.binder_debug, jobs=Options.jobs, gcc_install_prefix=Options.gcc_install_prefix, compiler=Options.compiler) if not Options.pybind11: Options.pybind11 = build.install_pybind11(source_path + '/build') diff --git a/build.py b/build.py index 6ac5db70..6e7e89cf 100644 --- a/build.py +++ b/build.py @@ -29,7 +29,7 @@ _python_version_ = '{}.{}'.format(sys.version_info.major, sys.version_info.minor) # should be formatted: 2.7, 3.5, 3.6, ... -_pybind11_version_ = '32c4d7e17f267e10e71138a78d559b1eef17c909' +_pybind11_version_ = 'aa304c9c7d725ffb9d10af08a3b34cb372307020' def execute(message, command_line, return_='status', until_successes=False, terminate_on_failure=True, silent=False, silence_output=False): @@ -81,10 +81,10 @@ def get_compiler_family(): return 'unknown' -def get_cmake_compiler_options(): +def get_cmake_compiler_options(compiler): ''' Get cmake compiler flags from Options.compiler ''' - if Platform == "linux" and Options.compiler == 'clang': return ' -DCMAKE_C_COMPILER=`which clang` -DCMAKE_CXX_COMPILER=`which clang++`' - if Platform == "linux" and Options.compiler == 'gcc': return ' -DCMAKE_C_COMPILER=`which gcc` -DCMAKE_CXX_COMPILER=`which g++`' + if Platform == "linux" and compiler == 'clang': return ' -DCMAKE_C_COMPILER=`which clang` -DCMAKE_CXX_COMPILER=`which clang++`' + if Platform == "linux" and compiler == 'gcc': return ' -DCMAKE_C_COMPILER=`which gcc` -DCMAKE_CXX_COMPILER=`which g++`' return '' @@ -175,7 +175,7 @@ def install_llvm_tool(name, source_location, prefix_root, debug, compiler, jobs, with open(cmake_lists, 'w') as f: f.write(tool_build_line + '\n') config = '-DCMAKE_BUILD_TYPE={build_type}'.format(build_type='Debug' if debug else 'Release') - config += get_cmake_compiler_options() + config += get_cmake_compiler_options(compiler) if not os.path.isdir(build_dir): os.makedirs(build_dir) execute( diff --git a/documentation/config.rst b/documentation/config.rst index 7c9305f1..ac86350e 100644 --- a/documentation/config.rst +++ b/documentation/config.rst @@ -69,6 +69,15 @@ Config file directives: +namespace utility +* ``enum``, specify if particular enum should be bound. Purpose of this directive is to allow developer to cherry-pick + particular enum from otherwise binded/skipped namespaces and mark it for binding/skipping. + +.. code-block:: bash + + -enum utility::pointer::State + +enum protocols::CDR_Type + + * ``class``, specify if particular class/struct should be bound. Purpose of this directive is to allow developer to cherry-pick particular class from otherwise binded/skipped namespaces and mark it for binding/skipping. @@ -78,6 +87,11 @@ Config file directives: -class utility::pointer::ReferenceCount -class std::__weak_ptr +* ``field``, specify if a particular field should be bound. + +.. code-block:: bash + + -field MyClass::some_field * ``python_builtin``, specify if particular class/struct should be considered a python builtin and assume existing bindings for it already exist. @@ -148,7 +162,7 @@ Config file directives: * ``+add_on_binder``, similar to ``binder``: specify custom binding function for class/struct that will be called `after` Binder generated code bound it. This allow developer to create extra bindings for particular type (bind special Python methods, - operators, etc.) + operators, etc.) The expected type signature of specified function should be `void f(pybind11::class_ > &)` .. code-block:: bash @@ -160,7 +174,7 @@ Config file directives: * ``+binder_for_namespace``, similar to ``binder``: specify custom binding function for namespace. Call to specified function will be generated - _instead_ of generating bindings for namaspace. + _instead_ of generating bindings for namaspace. Where expected type signature of specified function should be `void f(pybind11::module &)` .. code-block:: bash @@ -209,7 +223,7 @@ Config file directives: +default_member_rvalue_reference_return_value_policy pybind11::return_value_policy::move +default_call_guard pybind11::gil_scoped_release -* ``+custom_shared``: specify a custom shared pointer class that Binder should use instead of std::shared_ptr. +* ``+custom_shared``: specify a custom shared pointer class that Binder should use instead of ``std::shared_ptr``. * ``module_local_namespace``: use to add (or remove) the extra argument module_local to the pybind11 classes and enum of a namespace. This option can be used for all the namaspaces of a given project using `+module_local_namespace @all_namespaces`. @@ -218,10 +232,12 @@ Config file directives: +module_local_namespace @all_namespaces -module_local_namespace std -* ``trampoline_member_function_binder``: use to specify a custom trampoline member function defined by the user in a given header file. +* ``trampoline_member_function_binder``: use to specify a custom trampoline member function defined by the user in a given header file .. code-block:: bash +include_for_class aaa::A +trampoline_member_function_binder aaa::A::foo myFoo + +* ``+prefix_for_static_member_functions``: specify name prefix to use for static member functions, could be useful as workaround Pybind11 limitation restricting having both virtual and static member functions having the same name diff --git a/source/class.cpp b/source/class.cpp index 32b42194..4ff4688e 100644 --- a/source/class.cpp +++ b/source/class.cpp @@ -549,6 +549,21 @@ void ClassBinder::add_relevant_includes(IncludeSet &includes) const includes.add_include(" // __str__"); } +string generate_opaque_declaration_if_needed(string const & qualified_name, string const & qualified_name_without_template) +{ + // pybind11 container lists https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html + static vector stl_containers {"std::vector", "std::deque", "std::list", "std::array", "std::valarray", "std::set", "std::unordered_set", "std::map", "std::unordered_map"}; + + if( begins_with(qualified_name_without_template, "std::") ) { + auto it = std::find(stl_containers.begin(), stl_containers.end(), qualified_name_without_template); + if( it != stl_containers.end() ) { + return "PYBIND11_MAKE_OPAQUE(" + qualified_name + ");\n"; + } + } + + return ""; +} + string binding_public_data_members(CXXRecordDecl const *C) { string c; @@ -560,6 +575,10 @@ string binding_public_data_members(CXXRecordDecl const *C) for( auto s = u->shadow_begin(); s != u->shadow_end(); ++s ) { if( UsingShadowDecl *us = dyn_cast(*s) ) { if( FieldDecl *f = dyn_cast(us->getTargetDecl()) ) { + auto config = Config::get(); + if ( config.is_field_skipping_requested(f->getQualifiedNameAsString())) { + continue; + } if( is_bindable(f) ) c += "\tcl" + bind_data_member(f, class_qualified_name(C)) + ";\n"; } } @@ -571,6 +590,10 @@ string binding_public_data_members(CXXRecordDecl const *C) for( auto d = C->decls_begin(); d != C->decls_end(); ++d ) { if( FieldDecl *f = dyn_cast(*d) ) { //outs() << "Class: " << class_qualified_name(C); f->dump(); outs() << "\n"; + auto config = Config::get(); + if ( config.is_field_skipping_requested(f->getQualifiedNameAsString()) ) { + continue; + } if( f->getAccess() == AS_public and is_bindable(f) ) c += "\tcl" + bind_data_member(f, class_qualified_name(C)) + ";\n"; } } @@ -581,7 +604,7 @@ string binding_public_data_members(CXXRecordDecl const *C) inline string callback_structure_name(CXXRecordDecl const *C) { string ns = replace_(namespace_from_named_decl(C), "::", "_"); - return "PyCallBack_" + (ns.empty() ? "" : ns + '_') + python_class_name(C); + return mangle_type_name( "PyCallBack_" + (ns.empty() ? "" : ns + '_') + python_class_name(C), false ); } @@ -693,7 +716,7 @@ string bind_member_functions_for_call_back(CXXRecordDecl const *C, string const // (*m)->dump(); // } - string return_type = standard_name(m->getReturnType().getCanonicalType().getAsString()); + string return_type = standard_name(m->getReturnType()); fix_boolean_types(return_type); // check if we need to fix return class to be 'derived-class &' or 'derived-class *' @@ -1110,9 +1133,16 @@ std::string ClassBinder::bind_repr(Context &context, Config const &config) if( config.is_function_skipping_requested(qualified_name + "::__str__") or config.is_function_skipping_requested( standard_name(C->getQualifiedNameAsString() + "::__str__" ) ) ) return c; if( FunctionDecl const *F = context.global_insertion_operator(C) ) { - // outs() << "Found insertion operator for: " << class_qualified_name(C) << "\n"; + //outs() << "Found insertion operator for: " << class_qualified_name(C) << "\n"; + //outs() << "insertion operator: " << F->getNameInfo().getAsString() << " qn: " << F->getQualifiedNameAsString() << " dn:" << F->getDeclName() << "\n"; + + string maybe_using_decl; - c += "\n\tcl.def(\"__str__\", []({} const &o) -> std::string {{ std::ostringstream s; {}(s, o); return s.str(); }} );\n"_format(qualified_name, F->getQualifiedNameAsString()); + string ns = namespace_from_named_decl(F); + if(ns.size()) maybe_using_decl = " using namespace {};"_format(ns); + + //c += "\n\tcl.def(\"__str__\", []({} const &o) -> std::string {{ std::ostringstream s; {}(s, o); return s.str(); }} );\n"_format(qualified_name, F->getQualifiedNameAsString()); + c += "\n\tcl.def(\"__str__\", []({} const &o) -> std::string {{ std::ostringstream s;{} s << o; return s.str(); }} );\n"_format(qualified_name, maybe_using_decl); prefix_includes_.push_back(F); } @@ -1166,7 +1196,11 @@ void ClassBinder::bind(Context &context) { if( is_binded() ) return; + string const qualified_name = class_qualified_name(C); string const qualified_name_without_template = standard_name(C->getQualifiedNameAsString()); + + //prefix_code_ += generate_opaque_declaration_if_needed(qualified_name, qualified_name_without_template); + std::map const &external_binders = Config::get().binders(); if( external_binders.count(qualified_name_without_template) ) { bind_with(external_binders.at(qualified_name_without_template), context); @@ -1181,8 +1215,6 @@ void ClassBinder::bind(Context &context) if( trampoline ) generate_prefix_code(); - string const qualified_name{class_qualified_name(C)}; - bool named_class = not C->isAnonymousStructOrUnion(); // if( named_class and (qualified_name.rfind(')') != std::string::npos) ) named_class = false; // check for anonymous structs and types in anonymous namespaces diff --git a/source/class.hpp b/source/class.hpp index b01d0b5a..af0a5343 100644 --- a/source/class.hpp +++ b/source/class.hpp @@ -34,6 +34,10 @@ std::string template_specialization(clang::CXXRecordDecl const *C); std::string class_name(clang::CXXRecordDecl const *C); +// generate string represetiong class name that could be used in python +std::string python_class_name(clang::CXXRecordDecl const *C); + + // generate qualified class name that could be used in bindings code including template specialization if any std::string class_qualified_name(clang::CXXRecordDecl const *C); diff --git a/source/config.cpp b/source/config.cpp index 9cb8e5d2..19ce27d0 100644 --- a/source/config.cpp +++ b/source/config.cpp @@ -57,6 +57,8 @@ void Config::read(string const &file_name) string const _namespace_{"namespace"}; string const _function_{"function"}; string const _class_{"class"}; + string const _field_{"field"}; + string const _enum_{"enum"}; string const _python_builtin_{"python_builtin"}; @@ -89,6 +91,8 @@ void Config::read(string const &file_name) string const _default_call_guard_{"default_call_guard"}; + string const _prefix_for_static_member_functions_{"prefix_for_static_member_functions"}; + std::ifstream f(file_name); if( not f.good() ) { throw std::runtime_error("can not open file " + file_name + " for reading..."); } @@ -126,6 +130,11 @@ void Config::read(string const &file_name) if( bind ) classes_to_bind.push_back(name_without_spaces); else classes_to_skip.push_back(name_without_spaces); } + else if( token == _enum_ ) { + + if( bind ) enums_to_bind.push_back(name_without_spaces); + else enums_to_skip.push_back(name_without_spaces); + } else if( token == _python_builtin_ ) { if (bind) python_builtins.insert(name_without_spaces); @@ -178,28 +187,33 @@ void Config::read(string const &file_name) if( bind ) { auto binder_function = split_in_two(name, "Invalid line for binder specification! Must be: name_of_type + + name_of_binder. Got: " + line); - binders_[binder_function.first] = binder_function.second; + binders_[binder_function.first] = trim(binder_function.second); } } else if( token == _add_on_binder_ ) { if( bind ) { auto binder_function = split_in_two(name, "Invalid line for add_on_binder specification! Must be: name_of_type + + name_of_binder. Got: " + line); - add_on_binders_[binder_function.first] = binder_function.second; + add_on_binders_[binder_function.first] = trim(binder_function.second); } } else if( token == _binder_for_namespace_ ) { if( bind ) { auto binder_function = split_in_two(name, "Invalid line for binder_for_namespace specification! Must be: name_of_type + + name_of_binder. Got: " + line); - binder_for_namespaces_[binder_function.first] = binder_function.second; + binder_for_namespaces_[binder_function.first] = trim(binder_function.second); } } else if( token == _add_on_binder_for_namespace_ ) { if( bind ) { auto binder_function = split_in_two(name, "Invalid line for add_on_binder_for_namespace specification! Must be: name_of_type + + name_of_binder. Got: " + line); - add_on_binder_for_namespaces_[binder_function.first] = binder_function.second; + add_on_binder_for_namespaces_[binder_function.first] = trim(binder_function.second); + } + } else if ( token == _field_ ) { + + if (!bind) { + fields_to_skip.push_back(name_without_spaces); } } else if( token == _custom_shared_ ) holder_type_ = name_without_spaces; @@ -220,6 +234,8 @@ void Config::read(string const &file_name) else if( token == _default_member_rvalue_reference_return_value_policy_ ) default_member_rvalue_reference_return_value_policy_ = name_without_spaces; else if( token == _default_call_guard_ ) default_call_guard_ = name_without_spaces; + else if( token == _prefix_for_static_member_functions_ ) prefix_for_static_member_functions_ = name_without_spaces; + else if( token == _trampoline_member_function_binder_ ) { if( bind ) { auto member_function_name_and_function_name = split_in_two(name, "Invalid line for trampoline_member_function_binder specification! Must be: qualified_class_name::member_funtion_name + + name_of_function. Got: " + line); @@ -363,6 +379,33 @@ bool Config::is_class_skipping_requested(string const &class__) const } +bool Config::is_field_skipping_requested(string const &field_) const +{ + return std::find(fields_to_skip.begin(), fields_to_skip.end(), field_) != fields_to_skip.end(); +} + + +bool Config::is_enum_binding_requested(string const &enum_) const +{ + auto bind = std::find(enums_to_bind.begin(), enums_to_bind.end(), enum_); + + if( bind != enums_to_bind.end() ) return true; + + return false; +} + + +bool Config::is_enum_skipping_requested(string const &enum_) const +{ + auto bind = std::find(enums_to_skip.begin(), enums_to_skip.end(), enum_); + + if( bind != enums_to_skip.end() ) return true; + + return false; +} + + + string Config::is_custom_trampoline_function_requested(string const &function_) const { auto it = custom_trampoline_functions_.find(function_); diff --git a/source/config.hpp b/source/config.hpp index 00fb033e..65aa9195 100644 --- a/source/config.hpp +++ b/source/config.hpp @@ -53,6 +53,9 @@ class Config string default_call_guard_ = ""; string holder_type_ = "std::shared_ptr"; string include_file_ = "pybind11/pybind11.h"; + string prefix_for_static_member_functions_ = ""; + + std::vector enums_to_bind, enums_to_skip; public: static Config &get(); @@ -62,7 +65,7 @@ class Config string root_module; - std::vector namespaces_to_bind, classes_to_bind, functions_to_bind, namespaces_to_skip, classes_to_skip, functions_to_skip, includes_to_add, includes_to_skip; + std::vector namespaces_to_bind, classes_to_bind, functions_to_bind, namespaces_to_skip, classes_to_skip, functions_to_skip, includes_to_add, includes_to_skip, fields_to_skip; std::vector buffer_protocols, module_local_namespaces_to_add, module_local_namespaces_to_skip, smart_held_classes; std::map const &binders() const { return binders_; } @@ -85,6 +88,8 @@ class Config string const &default_member_rvalue_reference_return_value_policy() { return default_member_rvalue_reference_return_value_policy_; } string const &default_call_guard() { return default_call_guard_; } + string const &prefix_for_static_member_functions() { return prefix_for_static_member_functions_; } + string const &holder_type() const { return holder_type_; } string const &include_file() const { return include_file_; } @@ -102,6 +107,10 @@ class Config bool is_class_binding_requested(string const &class_) const; bool is_class_skipping_requested(string const &class_) const; + + bool is_enum_binding_requested(string const &enum_) const; + bool is_enum_skipping_requested(string const &enum_) const; + bool is_buffer_protocol_requested(string const &class_) const; bool is_smart_holder_requested(string const &class_) const; @@ -111,6 +120,8 @@ class Config string is_custom_trampoline_function_requested(string const &function__) const; string includes_code() const; + + bool is_field_skipping_requested(string const &name) const; }; diff --git a/source/enum.cpp b/source/enum.cpp index e8d4de8e..d39fd452 100644 --- a/source/enum.cpp +++ b/source/enum.cpp @@ -56,6 +56,33 @@ bool is_bindable(EnumDecl const *E) return true; } +/// check if user requested binding for the given declaration +bool is_binding_requested(clang::EnumDecl const *E, Config const &config) +{ + if( config.is_enum_binding_requested( E->getQualifiedNameAsString() ) ) return true; + + bool bind = config.is_namespace_binding_requested(namespace_from_named_decl(E)); + //for( auto &t : get_type_dependencies(E) ) bind &= !is_skipping_requested(t, config); + return bind; +} + +// check if user requested skipping for the given declaration +bool is_skipping_requested(clang::EnumDecl const *E, Config const &config) +{ + string qualified_name = standard_name(E->getQualifiedNameAsString()); + + if( config.is_enum_skipping_requested(qualified_name) ) return true; + if( config.is_enum_binding_requested(qualified_name) ) return false; + + bool skip = config.is_namespace_skipping_requested(namespace_from_named_decl(E)); + + //for( auto &t : get_type_dependencies(E) ) skip |= is_skipping_requested(t, config); + + return skip; +} + + + // This function takes care about the LLVM/Clang bug which was fixed in LLVM6/Clang6. // The body of the function is a backport from LLVM6. std::string getQualifiedNameAsStringLLVM5Fix(NamedDecl const *E) @@ -126,14 +153,15 @@ string EnumBinder::id() const /// check if generator can create binding bool EnumBinder::bindable() const { - return is_bindable(E); + return is_bindable(E) and !is_banned_symbol(E); } /// check if user requested binding for the given declaration void EnumBinder::request_bindings_and_skipping(Config const &config) { - if( config.is_namespace_binding_requested(namespace_from_named_decl(E)) ) Binder::request_bindings(); + if( is_skipping_requested(E, config) ) Binder::request_skipping(); + else if( is_binding_requested(E, config) ) Binder::request_bindings(); } diff --git a/source/enum.hpp b/source/enum.hpp index 016212f0..2cdf017e 100644 --- a/source/enum.hpp +++ b/source/enum.hpp @@ -30,6 +30,14 @@ void add_relevant_includes(clang::EnumDecl const *E, IncludeSet &includes, int l bool is_bindable(clang::EnumDecl const *E); +/// check if user requested binding for the given declaration +bool is_binding_requested(clang::EnumDecl const *E, Config const &config); + + +/// check if user requested skipping for the given declaration +bool is_skipping_requested(clang::EnumDecl const *E, Config const &config); + + // Generate binding for given function: py::enum_(module, "MyEnum")... std::string bind_enum(std::string const &module, clang::EnumDecl const *E); diff --git a/source/function.cpp b/source/function.cpp index 26690414..4f3f6343 100644 --- a/source/function.cpp +++ b/source/function.cpp @@ -94,7 +94,8 @@ string function_arguments(clang::FunctionDecl const *record) string r; for( uint i = 0; i < record->getNumParams(); ++i ) { - r += standard_name(record->getParamDecl(i)->getOriginalType().getCanonicalType().getAsString()); + //r += standard_name(record->getParamDecl(i)->getOriginalType().getCanonicalType().getAsString()); + r += standard_name(record->getParamDecl(i)->getOriginalType()); if( i + 1 != record->getNumParams() ) r += ", "; } @@ -112,8 +113,8 @@ pair function_arguments_for_lambda(clang::FunctionDecl const *re string r, a; for( uint i = 0; i < record->getNumParams() and i < n; ++i ) { - QualType qt = record->getParamDecl(i)->getOriginalType().getCanonicalType(); - r += standard_name(qt.getAsString()) + ' '; + QualType qt = record->getParamDecl(i)->getOriginalType(); + r += standard_name(qt) + ' '; if( !qt->isReferenceType() and !qt->isPointerType() ) r += !qt.isConstQualified() ? "const & " : "& "; r += "a" + std::to_string(i); a += "a" + std::to_string(i); @@ -137,8 +138,8 @@ tuple function_arguments_for_py_overload(clang::Function string r, a, p; for( uint i = 0; i < record->getNumParams(); ++i ) { - QualType qt = record->getParamDecl(i)->getOriginalType().getCanonicalType(); - r += standard_name(qt.getAsString()) + ' ' + "a" + std::to_string(i); + QualType qt = record->getParamDecl(i)->getOriginalType(); + r += standard_name(qt) + ' ' + "a" + std::to_string(i); a += "a" + std::to_string(i); p += string(qt->isLValueReferenceType() ? "&" : "") + "a" + std::to_string(i); if( i + 1 != record->getNumParams() ) { @@ -244,6 +245,7 @@ string python_function_name(FunctionDecl const *F) // Generate function pointer type string for given function: void (*)(int, doule)_ or void (ClassName::*)(int, doule)_ for memeber function string function_pointer_type(FunctionDecl const *F) { + //F->dump(); string r; string prefix, maybe_const; if( auto m = dyn_cast(F) ) { @@ -251,7 +253,9 @@ string function_pointer_type(FunctionDecl const *F) maybe_const = m->isConst() ? " const" : ""; } - r += standard_name(F->getReturnType().getCanonicalType().getAsString()); + //r += standard_name(F->getReturnType().getCanonicalType().getAsString()); + r += standard_name(F->getReturnType()); + r += " ({}*)("_format(prefix); r += function_arguments(F); @@ -270,7 +274,7 @@ string function_qualified_name(FunctionDecl const *F, bool omit_return_type) string maybe_const; if( auto m = dyn_cast(F) ) maybe_const = m->isConst() ? " const" : ""; - string r = (omit_return_type ? "" : F->getReturnType().getCanonicalType().getAsString() + " ") + standard_name(F->getQualifiedNameAsString() + template_specialization(F)) + "(" + + string r = (omit_return_type ? "" : standard_name(F->getReturnType()) + " ") + standard_name(F->getQualifiedNameAsString() + template_specialization(F)) + "(" + function_arguments(F) + ")" + maybe_const; fix_boolean_types(r); @@ -363,7 +367,13 @@ string bind_function(FunctionDecl const *F, uint args_to_bind, bool request_bind string function_qualified_name = standard_name(parent ? class_qualified_name(parent) + "::" + F->getNameAsString() : F->getQualifiedNameAsString()); CXXMethodDecl const *m = dyn_cast(F); - string maybe_static = m and m->isStatic() ? "_static" : ""; + + string maybe_static; + if( m and m->isStatic() ) { + maybe_static = "_static"; + function_name = Config::get().prefix_for_static_member_functions() + function_name; + //outs() << "STATIC: " << function_qualified_name << " → " << function_name << "\n"; + } string function, documentation; if( args_to_bind == F->getNumParams() and (not always_use_lambda) ) { @@ -372,13 +382,13 @@ string bind_function(FunctionDecl const *F, uint args_to_bind, bool request_bind documentation = generate_documentation_string_for_declaration(F); if( documentation.size() ) documentation += "\\n\\n"; documentation += "C++: " + standard_name(F->getQualifiedNameAsString() + "(" + function_arguments(F) + ')' + (m and m->isConst() ? " const" : "") + " --> " + - F->getReturnType().getCanonicalType().getAsString()); + standard_name(F->getReturnType() ) ); } else { pair args = function_arguments_for_lambda(F, args_to_bind); // string args; for(uint i=0; igetReturnType().getCanonicalType().getAsString()); + string return_type = standard_name(F->getReturnType()); // workaround of GCC bug during lambda specification: replace enum/struct/class/const_* from begining of the lambda return type with //const* static vector< std::pair > const name_map = { diff --git a/source/stl_binders.hpp b/source/stl_binders.hpp index a922e187..3cd28f39 100644 --- a/source/stl_binders.hpp +++ b/source/stl_binders.hpp @@ -64,13 +64,17 @@ template class vector_binder template class map_binder { public: - map_binder(pybind11::module &m, std::string const &key_name, std::string const &value_name, std::string const & /*compare name*/, std::string const & /*allocator name*/) + map_binder(pybind11::module &m, std::string const &key_name, std::string const &value_name, std::string const & comparator_name, std::string const & allocator_name) { using Map = std::map; using holder_type = std::shared_ptr< std::map >; using Class_ = pybind11::class_; - Class_ cl = pybind11::bind_map(m, "map_" + key_name + '_' + value_name); + std::string maybe_extra = + ( (comparator_name == "std_less_" + key_name + "_t") ? "" : ("_" + comparator_name) ) + + ( (allocator_name == "std_allocator_std_pair_const_" + key_name + '_' + value_name + "_t") ? "" : ("_" + allocator_name) ); + + Class_ cl = pybind11::bind_map(m, "map_" + key_name + '_' + value_name + maybe_extra); } }; diff --git a/source/type.cpp b/source/type.cpp index 6532bbd4..2adf346d 100644 --- a/source/type.cpp +++ b/source/type.cpp @@ -455,6 +455,26 @@ void request_bindings(clang::QualType const &qt, Context &context) } +/// return standard string representation of a given type +std::string standard_name(clang::QualType const &qt) +{ + //qt.dump(); + string r = qt.getAsString(); + + // if( r == "std::array::size_type" ) { + // //if( begins_with(r, "std::array<" ) ) { + // outs() << "--> " << r << '\n'; + // qt.dump(); + // } + + // if( begins_with(r, "std::") ) return r; //standard_name(r); + static std::set standard_names {"std::size_t"}; + + if( standard_names.count(r) ) return r; + else return standard_name(qt.getCanonicalType().getAsString()); +} + + // transform give type name to standard form string standard_name_raw(string const &type) { diff --git a/source/type.hpp b/source/type.hpp index f3f04945..78f298e1 100644 --- a/source/type.hpp +++ b/source/type.hpp @@ -54,6 +54,10 @@ bool is_bindable(clang::QualType const &qt); void request_bindings(clang::QualType const &qt, Context &context); +/// return standard string representation of a given type +std::string standard_name(clang::QualType const &qt); + + /// transform give type name to standard form std::string standard_name(std::string const &type); diff --git a/source/util.cpp b/source/util.cpp index 1e50e706..cbfab801 100644 --- a/source/util.cpp +++ b/source/util.cpp @@ -110,6 +110,20 @@ string indent(string const &code, string const &indentation) } +/// remove leading and trailing tabs and spaces +std::string trim(std::string const &s) +{ + static std::string const whitespaces = " \t"; + + auto begin = s.find_first_not_of(whitespaces); + if(begin == std::string::npos) return ""; + + auto end = s.find_last_not_of(whitespaces); + + return s.substr(begin, end - begin + 1); +} + + /// Try to read exisitng file and if content does not match to code - write a new version. Also create nested dirs starting from prefix if nessesary. void update_source_file(std::string const &prefix, std::string const &file_name, std::string const &code) { @@ -252,24 +266,20 @@ string line_number(NamedDecl const *decl) string mangle_type_name(string const &name, bool mark_template) { string r; - bool mangle = true; bool template_ = false; for( auto &c : name ) { - if( c != ' ' and c != '<' and c != '>' and c != ',' and c != ':' ) { - r.push_back(c); - mangle = false; - } - else if( !mangle ) { - mangle = true; - r.push_back('_'); + if( c == ' ' or c == '<' or c == '>' or c == ',' or c == ':' ) { + if( r.empty() or r.back() != '_' ) r.push_back('_'); } + else r.push_back(c); if( c == '<' or c == '>' or c == ',' ) template_ = true; } if( template_ and mark_template ) { replace(r, "*", "_star_"); + replace(r, "&", "_ref_"); r.push_back('t'); } diff --git a/source/util.hpp b/source/util.hpp index 106440da..ebb50947 100644 --- a/source/util.hpp +++ b/source/util.hpp @@ -44,6 +44,8 @@ bool ends_with(std::string const &source, std::string const &prefix); /// indent given code std::string indent(std::string const &code, std::string const &indentation); +/// remove leading and trailing tabs and spaces +std::string trim(std::string const &s); /// Try to read existing file. If file content does not match given code, overwrite the file with code. Also create nested dirs starting from prefix if nessesary. void update_source_file(std::string const &prefix, std::string const &file_name, std::string const &code); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b9f3e1e6..e2380340 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -36,6 +36,7 @@ else() -- -x c++ -std=c++11 -I . -I ${CMAKE_CURRENT_SOURCE_DIR} -isystem / -I ${CLANG_INCLUDE_DIRS} -iwithsysroot${LibClang_INCLUDE_DIR} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" VERBATIM) endif() + add_dependencies(target${stestnamenodot}cpp binder) endif() endmacro( binder_src stestname) diff --git a/test/T00.basic.ref b/test/T00.basic.ref.cpp similarity index 100% rename from test/T00.basic.ref rename to test/T00.basic.ref.cpp diff --git a/test/T01.enum.config b/test/T01.enum.config new file mode 100644 index 00000000..58493b69 --- /dev/null +++ b/test/T01.enum.config @@ -0,0 +1,6 @@ +-namespace aaaa + +-enum E6_class_not_binded ++enum aaaa::E7_class + +-field A::field1 \ No newline at end of file diff --git a/test/T01.enum.hpp b/test/T01.enum.hpp index 2e22d227..494be86d 100644 --- a/test/T01.enum.hpp +++ b/test/T01.enum.hpp @@ -26,6 +26,9 @@ class A enum struct AE2_struct { AE3_V0, AE3_V1 }; enum class AE3_class { AE2_V0, AE2_V1 }; + int field1 = 0; + int field2 = 0; + protected: enum AE3_not_binded { AE3_V0_not_binded, AE3_V1_not_binded }; enum class AE4_not_binded { AE4_V0_not_binded, AE4_V1_not_binded }; @@ -35,4 +38,13 @@ class A enum class AE6_not_binded { AE6_V0_not_binded, AE6_V1_not_binded }; }; + +enum class E6_class_not_binded { V0, V1 }; + + +namespace aaaa { +enum class E7_class { V0, V1 }; +enum class E8_class_not_binded { V0, V1 }; +} + #endif // _INCLUDED_T01_enum_hpp_ diff --git a/test/T01.enum.ref b/test/T01.enum.ref.cpp similarity index 79% rename from test/T01.enum.ref rename to test/T01.enum.ref.cpp index 5c8e2e72..f8efe690 100644 --- a/test/T01.enum.ref +++ b/test/T01.enum.ref.cpp @@ -61,10 +61,37 @@ void bind_T01_enum(std::function< pybind11::module &(std::string const &namespac .value("AE2_V0", A::AE3_class::AE2_V0) .value("AE2_V1", A::AE3_class::AE2_V1); + cl.def_readwrite("field2", &A::field2); } } +// File: T01_enum_1.cpp +#include // aaaa::E7_class + +#include +#include +#include + +#ifndef BINDER_PYBIND11_TYPE_CASTER + #define BINDER_PYBIND11_TYPE_CASTER + PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) + PYBIND11_DECLARE_HOLDER_TYPE(T, T*) + PYBIND11_MAKE_OPAQUE(std::shared_ptr) +#endif + +void bind_T01_enum_1(std::function< pybind11::module &(std::string const &namespace_) > &M) +{ + // aaaa::E7_class file:T01.enum.hpp line:46 + pybind11::enum_(M("aaaa"), "E7_class", "") + .value("V0", aaaa::E7_class::V0) + .value("V1", aaaa::E7_class::V1); + +; + +} + + #include #include #include @@ -77,6 +104,7 @@ void bind_T01_enum(std::function< pybind11::module &(std::string const &namespac typedef std::function< pybind11::module & (std::string const &) > ModuleGetter; void bind_T01_enum(std::function< pybind11::module &(std::string const &namespace_) > &M); +void bind_T01_enum_1(std::function< pybind11::module &(std::string const &namespace_) > &M); PYBIND11_MODULE(T01_enum, root_module) { @@ -101,18 +129,21 @@ PYBIND11_MODULE(T01_enum, root_module) { ); std::vector< std::pair > sub_modules { + {"", "aaaa"}, }; for(auto &p : sub_modules ) modules[p.first.size() ? p.first+"::"+p.second : p.second] = modules[p.first].def_submodule( mangle_namespace_name(p.second).c_str(), ("Bindings for " + p.first + "::" + p.second + " namespace").c_str() ); //pybind11::class_>(M(""), "_encapsulated_data_"); bind_T01_enum(M); + bind_T01_enum_1(M); } // Source list file: TEST/T01_enum.sources // T01_enum.cpp // T01_enum.cpp +// T01_enum_1.cpp // Modules list file: TEST/T01_enum.modules -// +// aaaa diff --git a/test/T02.function.ref b/test/T02.function.ref.cpp similarity index 100% rename from test/T02.function.ref rename to test/T02.function.ref.cpp diff --git a/test/T05.default.ref b/test/T05.default.ref.cpp similarity index 100% rename from test/T05.default.ref rename to test/T05.default.ref.cpp diff --git a/test/T07.class.match_args.ref b/test/T07.class.match_args.ref.cpp similarity index 100% rename from test/T07.class.match_args.ref rename to test/T07.class.match_args.ref.cpp diff --git a/test/T07.class.ref b/test/T07.class.ref.cpp similarity index 100% rename from test/T07.class.ref rename to test/T07.class.ref.cpp diff --git a/test/T08.constructor.ref b/test/T08.constructor.ref.cpp similarity index 100% rename from test/T08.constructor.ref rename to test/T08.constructor.ref.cpp diff --git a/test/T09.overload.ref b/test/T09.overload.ref.cpp similarity index 100% rename from test/T09.overload.ref rename to test/T09.overload.ref.cpp diff --git a/test/T10.inheritance.ref b/test/T10.inheritance.ref.cpp similarity index 100% rename from test/T10.inheritance.ref rename to test/T10.inheritance.ref.cpp diff --git a/test/T10.virtual_inheritance.ref b/test/T10.virtual_inheritance.ref.cpp similarity index 100% rename from test/T10.virtual_inheritance.ref rename to test/T10.virtual_inheritance.ref.cpp diff --git a/test/T11.override.ref b/test/T11.override.ref.cpp similarity index 100% rename from test/T11.override.ref rename to test/T11.override.ref.cpp diff --git a/test/T12.insertion_operator.hpp b/test/T12.insertion_operator.hpp index c52561dd..39a98bd1 100644 --- a/test/T12.insertion_operator.hpp +++ b/test/T12.insertion_operator.hpp @@ -27,3 +27,44 @@ struct T inline std::ostream & operator<<(std::ostream & s, T const &) { return s << "hi..."; } } + +// https://github.com/RosettaCommons/binder/issues/236 +struct A1 { int a; }; + +namespace bbbb { + +std::ostream & operator<<(std::ostream & s, const A1 & a1) { return s; } + + + + +struct B; +namespace cccc { +std::ostream & operator <<(std::ostream & os, B const &b); +} + +struct B +{ + friend std::ostream & ::bbbb::cccc::operator <<(std::ostream & os, B const &); +private: + int b; +}; + + +struct B2 +{ + friend std::ostream & operator <<(std::ostream & os, B2 const &) { return os; } +}; + + +namespace cccc { +std::ostream & operator <<(std::ostream & os, B const &b) { os << b.b; return os; } + +struct C +{ + friend std::ostream & operator <<(std::ostream & os, C const &) { return os; } +}; + +} // namespace cccc + +} // namespace bbbb diff --git a/test/T12.insertion_operator.ref b/test/T12.insertion_operator.ref deleted file mode 100644 index dcde75eb..00000000 --- a/test/T12.insertion_operator.ref +++ /dev/null @@ -1,120 +0,0 @@ -// File: T12_insertion_operator.cpp -#include // A -#include // operator<< -#include // std::_Ios_Seekdir -#include // std::locale -#include // std::basic_ostream -#include // __str__ -#include // std::basic_streambuf -#include // std::char_traits - -#include -#include -#include - -#ifndef BINDER_PYBIND11_TYPE_CASTER - #define BINDER_PYBIND11_TYPE_CASTER - PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) - PYBIND11_DECLARE_HOLDER_TYPE(T, T*) - PYBIND11_MAKE_OPAQUE(std::shared_ptr) -#endif - -void bind_T12_insertion_operator(std::function< pybind11::module &(std::string const &namespace_) > &M) -{ - { // A file:T12.insertion_operator.hpp line:17 - pybind11::class_> cl(M(""), "A", ""); - cl.def( pybind11::init( [](){ return new A(); } ) ); - - cl.def("__str__", [](A const &o) -> std::string { std::ostringstream s; operator<<(s, o); return s.str(); } ); - } -} - - -// File: T12_insertion_operator_1.cpp -#include // aaaa::T -#include // aaaa::operator<< -#include // std::_Ios_Seekdir -#include // std::locale -#include // std::basic_ostream -#include // __str__ -#include // std::basic_streambuf -#include // std::char_traits - -#include -#include -#include - -#ifndef BINDER_PYBIND11_TYPE_CASTER - #define BINDER_PYBIND11_TYPE_CASTER - PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) - PYBIND11_DECLARE_HOLDER_TYPE(T, T*) - PYBIND11_MAKE_OPAQUE(std::shared_ptr) -#endif - -void bind_T12_insertion_operator_1(std::function< pybind11::module &(std::string const &namespace_) > &M) -{ - { // aaaa::T file:T12.insertion_operator.hpp line:23 - pybind11::class_> cl(M("aaaa"), "T", ""); - cl.def( pybind11::init( [](){ return new aaaa::T(); } ) ); - cl.def( pybind11::init( [](aaaa::T const &o){ return new aaaa::T(o); } ) ); - - cl.def("__str__", [](aaaa::T const &o) -> std::string { std::ostringstream s; aaaa::operator<<(s, o); return s.str(); } ); - } -} - - -#include -#include -#include -#include -#include -#include - -#include - -typedef std::function< pybind11::module & (std::string const &) > ModuleGetter; - -void bind_T12_insertion_operator(std::function< pybind11::module &(std::string const &namespace_) > &M); -void bind_T12_insertion_operator_1(std::function< pybind11::module &(std::string const &namespace_) > &M); - - -PYBIND11_MODULE(T12_insertion_operator, root_module) { - root_module.doc() = "T12_insertion_operator module"; - - std::map modules; - ModuleGetter M = [&](std::string const &namespace_) -> pybind11::module & { - auto it = modules.find(namespace_); - if( it == modules.end() ) throw std::runtime_error("Attempt to access pybind11::module for namespace " + namespace_ + " before it was created!!!"); - return it->second; - }; - - modules[""] = root_module; - - static std::vector const reserved_python_words {"nonlocal", "global", }; - - auto mangle_namespace_name( - [](std::string const &ns) -> std::string { - if ( std::find(reserved_python_words.begin(), reserved_python_words.end(), ns) == reserved_python_words.end() ) return ns; - else return ns+'_'; - } - ); - - std::vector< std::pair > sub_modules { - {"", "aaaa"}, - }; - for(auto &p : sub_modules ) modules[p.first.size() ? p.first+"::"+p.second : p.second] = modules[p.first].def_submodule( mangle_namespace_name(p.second).c_str(), ("Bindings for " + p.first + "::" + p.second + " namespace").c_str() ); - - //pybind11::class_>(M(""), "_encapsulated_data_"); - - bind_T12_insertion_operator(M); - bind_T12_insertion_operator_1(M); - -} - -// Source list file: TEST/T12_insertion_operator.sources -// T12_insertion_operator.cpp -// T12_insertion_operator.cpp -// T12_insertion_operator_1.cpp - -// Modules list file: TEST/T12_insertion_operator.modules -// aaaa diff --git a/test/T12.insertion_operator.ref.cpp b/test/T12.insertion_operator.ref.cpp new file mode 100644 index 00000000..aeff5654 --- /dev/null +++ b/test/T12.insertion_operator.ref.cpp @@ -0,0 +1,237 @@ +// File: T12_insertion_operator.cpp +#include // A +#include // operator<< +#include // std::_Ios_Seekdir +#include // std::locale +#include // std::basic_ostream +#include // __str__ +#include // std::basic_streambuf +#include // std::char_traits + +#include +#include +#include + +#ifndef BINDER_PYBIND11_TYPE_CASTER + #define BINDER_PYBIND11_TYPE_CASTER + PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) + PYBIND11_DECLARE_HOLDER_TYPE(T, T*) + PYBIND11_MAKE_OPAQUE(std::shared_ptr) +#endif + +void bind_T12_insertion_operator(std::function< pybind11::module &(std::string const &namespace_) > &M) +{ + { // A file:T12.insertion_operator.hpp line:17 + pybind11::class_> cl(M(""), "A", ""); + cl.def( pybind11::init( [](){ return new A(); } ) ); + + cl.def("__str__", [](A const &o) -> std::string { std::ostringstream s; s << o; return s.str(); } ); + } +} + + +// File: T12_insertion_operator_1.cpp +#include // aaaa::T +#include // aaaa::operator<< +#include // std::_Ios_Seekdir +#include // std::locale +#include // std::basic_ostream +#include // __str__ +#include // std::basic_streambuf +#include // std::char_traits + +#include +#include +#include + +#ifndef BINDER_PYBIND11_TYPE_CASTER + #define BINDER_PYBIND11_TYPE_CASTER + PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) + PYBIND11_DECLARE_HOLDER_TYPE(T, T*) + PYBIND11_MAKE_OPAQUE(std::shared_ptr) +#endif + +void bind_T12_insertion_operator_1(std::function< pybind11::module &(std::string const &namespace_) > &M) +{ + { // aaaa::T file:T12.insertion_operator.hpp line:23 + pybind11::class_> cl(M("aaaa"), "T", ""); + cl.def( pybind11::init( [](){ return new aaaa::T(); } ) ); + cl.def( pybind11::init( [](aaaa::T const &o){ return new aaaa::T(o); } ) ); + + cl.def("__str__", [](aaaa::T const &o) -> std::string { std::ostringstream s; using namespace aaaa; s << o; return s.str(); } ); + } +} + + +// File: T12_insertion_operator_2.cpp +#include // A1 +#include // bbbb::operator<< +#include // std::_Ios_Seekdir +#include // std::locale +#include // std::basic_ostream +#include // __str__ +#include // std::basic_streambuf +#include // std::char_traits + +#include +#include +#include + +#ifndef BINDER_PYBIND11_TYPE_CASTER + #define BINDER_PYBIND11_TYPE_CASTER + PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) + PYBIND11_DECLARE_HOLDER_TYPE(T, T*) + PYBIND11_MAKE_OPAQUE(std::shared_ptr) +#endif + +void bind_T12_insertion_operator_2(std::function< pybind11::module &(std::string const &namespace_) > &M) +{ + { // A1 file:T12.insertion_operator.hpp line:32 + pybind11::class_> cl(M(""), "A1", ""); + cl.def( pybind11::init( [](){ return new A1(); } ) ); + cl.def_readwrite("a", &A1::a); + + cl.def("__str__", [](A1 const &o) -> std::string { std::ostringstream s; using namespace bbbb; s << o; return s.str(); } ); + } +} + + +// File: T12_insertion_operator_3.cpp +#include // bbbb::B +#include // bbbb::B2 +#include // bbbb::cccc::operator<< +#include // bbbb::operator<< +#include // std::_Ios_Seekdir +#include // std::locale +#include // std::basic_ostream +#include // __str__ +#include // std::basic_streambuf +#include // std::char_traits + +#include +#include +#include + +#ifndef BINDER_PYBIND11_TYPE_CASTER + #define BINDER_PYBIND11_TYPE_CASTER + PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) + PYBIND11_DECLARE_HOLDER_TYPE(T, T*) + PYBIND11_MAKE_OPAQUE(std::shared_ptr) +#endif + +void bind_T12_insertion_operator_3(std::function< pybind11::module &(std::string const &namespace_) > &M) +{ + { // bbbb::B file:T12.insertion_operator.hpp line:46 + pybind11::class_> cl(M("bbbb"), "B", ""); + cl.def( pybind11::init( [](){ return new bbbb::B(); } ) ); + cl.def( pybind11::init( [](bbbb::B const &o){ return new bbbb::B(o); } ) ); + + cl.def("__str__", [](bbbb::B const &o) -> std::string { std::ostringstream s; using namespace bbbb::cccc; s << o; return s.str(); } ); + } + { // bbbb::B2 file:T12.insertion_operator.hpp line:54 + pybind11::class_> cl(M("bbbb"), "B2", ""); + cl.def( pybind11::init( [](){ return new bbbb::B2(); } ) ); + + cl.def("__str__", [](bbbb::B2 const &o) -> std::string { std::ostringstream s; using namespace bbbb; s << o; return s.str(); } ); + } +} + + +// File: T12_insertion_operator_4.cpp +#include // bbbb::cccc::C +#include // bbbb::cccc::operator<< +#include // std::_Ios_Seekdir +#include // std::locale +#include // std::basic_ostream +#include // __str__ +#include // std::basic_streambuf +#include // std::char_traits + +#include +#include +#include + +#ifndef BINDER_PYBIND11_TYPE_CASTER + #define BINDER_PYBIND11_TYPE_CASTER + PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) + PYBIND11_DECLARE_HOLDER_TYPE(T, T*) + PYBIND11_MAKE_OPAQUE(std::shared_ptr) +#endif + +void bind_T12_insertion_operator_4(std::function< pybind11::module &(std::string const &namespace_) > &M) +{ + { // bbbb::cccc::C file:T12.insertion_operator.hpp line:63 + pybind11::class_> cl(M("bbbb::cccc"), "C", ""); + cl.def( pybind11::init( [](){ return new bbbb::cccc::C(); } ) ); + + cl.def("__str__", [](bbbb::cccc::C const &o) -> std::string { std::ostringstream s; using namespace bbbb::cccc; s << o; return s.str(); } ); + } +} + + +#include +#include +#include +#include +#include +#include + +#include + +typedef std::function< pybind11::module & (std::string const &) > ModuleGetter; + +void bind_T12_insertion_operator(std::function< pybind11::module &(std::string const &namespace_) > &M); +void bind_T12_insertion_operator_1(std::function< pybind11::module &(std::string const &namespace_) > &M); +void bind_T12_insertion_operator_2(std::function< pybind11::module &(std::string const &namespace_) > &M); +void bind_T12_insertion_operator_3(std::function< pybind11::module &(std::string const &namespace_) > &M); +void bind_T12_insertion_operator_4(std::function< pybind11::module &(std::string const &namespace_) > &M); + + +PYBIND11_MODULE(T12_insertion_operator, root_module) { + root_module.doc() = "T12_insertion_operator module"; + + std::map modules; + ModuleGetter M = [&](std::string const &namespace_) -> pybind11::module & { + auto it = modules.find(namespace_); + if( it == modules.end() ) throw std::runtime_error("Attempt to access pybind11::module for namespace " + namespace_ + " before it was created!!!"); + return it->second; + }; + + modules[""] = root_module; + + static std::vector const reserved_python_words {"nonlocal", "global", }; + + auto mangle_namespace_name( + [](std::string const &ns) -> std::string { + if ( std::find(reserved_python_words.begin(), reserved_python_words.end(), ns) == reserved_python_words.end() ) return ns; + else return ns+'_'; + } + ); + + std::vector< std::pair > sub_modules { + {"", "aaaa"}, + {"", "bbbb"}, + {"bbbb", "cccc"}, + }; + for(auto &p : sub_modules ) modules[p.first.size() ? p.first+"::"+p.second : p.second] = modules[p.first].def_submodule( mangle_namespace_name(p.second).c_str(), ("Bindings for " + p.first + "::" + p.second + " namespace").c_str() ); + + //pybind11::class_>(M(""), "_encapsulated_data_"); + + bind_T12_insertion_operator(M); + bind_T12_insertion_operator_1(M); + bind_T12_insertion_operator_2(M); + bind_T12_insertion_operator_3(M); + bind_T12_insertion_operator_4(M); + +} + +// Source list file: TEST/T12_insertion_operator.sources +// T12_insertion_operator.cpp +// T12_insertion_operator.cpp +// T12_insertion_operator_1.cpp +// T12_insertion_operator_2.cpp +// T12_insertion_operator_3.cpp +// T12_insertion_operator_4.cpp + +// Modules list file: TEST/T12_insertion_operator.modules +// aaaa bbbb bbbb.cccc diff --git a/test/T12.operator.ref b/test/T12.operator.ref.cpp similarity index 100% rename from test/T12.operator.ref rename to test/T12.operator.ref.cpp diff --git a/test/T15.copy.ref b/test/T15.copy.ref.cpp similarity index 100% rename from test/T15.copy.ref rename to test/T15.copy.ref.cpp diff --git a/test/T15.inner_class.fwd.ref b/test/T15.inner_class.fwd.ref.cpp similarity index 100% rename from test/T15.inner_class.fwd.ref rename to test/T15.inner_class.fwd.ref.cpp diff --git a/test/T15.inner_class.ref b/test/T15.inner_class.ref.cpp similarity index 100% rename from test/T15.inner_class.ref rename to test/T15.inner_class.ref.cpp diff --git a/test/T17.anonymous.ref b/test/T17.anonymous.ref.cpp similarity index 100% rename from test/T17.anonymous.ref rename to test/T17.anonymous.ref.cpp diff --git a/test/T20.template.ref b/test/T20.template.ref.cpp similarity index 100% rename from test/T20.template.ref rename to test/T20.template.ref.cpp diff --git a/test/T20.template.variadic.ref b/test/T20.template.variadic.ref.cpp similarity index 100% rename from test/T20.template.variadic.ref rename to test/T20.template.variadic.ref.cpp diff --git a/test/T30.include.ref b/test/T30.include.ref.cpp similarity index 100% rename from test/T30.include.ref rename to test/T30.include.ref.cpp diff --git a/test/T31.include_for_class.ref b/test/T31.include_for_class.ref.cpp similarity index 98% rename from test/T31.include_for_class.ref rename to test/T31.include_for_class.ref.cpp index 4d3be880..8e901810 100644 --- a/test/T31.include_for_class.ref +++ b/test/T31.include_for_class.ref.cpp @@ -25,7 +25,7 @@ void bind_T31_include_for_class_incl_a_include(std::function< pybind11::module & pybind11::class_> cl(M("aaaa"), "A", ""); cl.def( pybind11::init( [](){ return new aaaa::A(); } ) ); - cl.def("__str__", [](aaaa::A const &o) -> std::string { std::ostringstream s; aaaa::cccc::operator<<(s, o); return s.str(); } ); + cl.def("__str__", [](aaaa::A const &o) -> std::string { std::ostringstream s; using namespace aaaa::cccc; s << o; return s.str(); } ); } } diff --git a/test/T32.call_guard.ref b/test/T32.call_guard.ref.cpp similarity index 100% rename from test/T32.call_guard.ref rename to test/T32.call_guard.ref.cpp diff --git a/test/T33.buffer_protocol.ref b/test/T33.buffer_protocol.ref.cpp similarity index 100% rename from test/T33.buffer_protocol.ref rename to test/T33.buffer_protocol.ref.cpp diff --git a/test/T40.stl.ref b/test/T40.stl.ref.cpp similarity index 100% rename from test/T40.stl.ref rename to test/T40.stl.ref.cpp diff --git a/test/T42.stl.names.map.ref b/test/T42.stl.names.map.ref.cpp similarity index 99% rename from test/T42.stl.names.map.ref rename to test/T42.stl.names.map.ref.cpp index 5542aba8..421de1f0 100644 --- a/test/T42.stl.names.map.ref +++ b/test/T42.stl.names.map.ref.cpp @@ -82,13 +82,13 @@ void bind_std_functional_hash(std::function< pybind11::module &(std::string cons pybind11::class_, std::shared_ptr>> cl(M("std"), "hash_float_t", ""); cl.def( pybind11::init( [](){ return new std::hash(); } ) ); cl.def( pybind11::init( [](std::hash const &o){ return new std::hash(o); } ) ); - cl.def("__call__", (unsigned long (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> unsigned long", pybind11::arg("__val")); + cl.def("__call__", (std::size_t (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> std::size_t", pybind11::arg("__val")); cl.def("assign", (struct std::hash & (std::hash::*)(const struct std::hash &)) &std::hash::operator=, "C++: std::hash::operator=(const struct std::hash &) --> struct std::hash &", pybind11::return_value_policy::automatic, pybind11::arg("")); } { // std::hash file:bits/basic_string.h line:3044 pybind11::class_, std::shared_ptr>> cl(M("std"), "hash_std_string_t", ""); cl.def( pybind11::init( [](){ return new std::hash(); } ) ); - cl.def("__call__", (unsigned long (std::hash::*)(const std::string &) const) &std::hash::operator(), "C++: std::hash::operator()(const std::string &) const --> unsigned long", pybind11::arg("__s")); + cl.def("__call__", (std::size_t (std::hash::*)(const std::string &) const) &std::hash::operator(), "C++: std::hash::operator()(const std::string &) const --> std::size_t", pybind11::arg("__s")); } { // std::map file:bits/stl_map.h line:96 pybind11::class_, std::shared_ptr>> cl(M("std"), "map_float_int_t", ""); diff --git a/test/T42.stl.names.multi.ref b/test/T42.stl.names.multi.ref.cpp similarity index 99% rename from test/T42.stl.names.multi.ref rename to test/T42.stl.names.multi.ref.cpp index d91ab560..35c7ef2b 100644 --- a/test/T42.stl.names.multi.ref +++ b/test/T42.stl.names.multi.ref.cpp @@ -82,13 +82,13 @@ void bind_std_functional_hash(std::function< pybind11::module &(std::string cons pybind11::class_, std::shared_ptr>> cl(M("std"), "hash_float_t", ""); cl.def( pybind11::init( [](){ return new std::hash(); } ) ); cl.def( pybind11::init( [](std::hash const &o){ return new std::hash(o); } ) ); - cl.def("__call__", (unsigned long (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> unsigned long", pybind11::arg("__val")); + cl.def("__call__", (std::size_t (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> std::size_t", pybind11::arg("__val")); cl.def("assign", (struct std::hash & (std::hash::*)(const struct std::hash &)) &std::hash::operator=, "C++: std::hash::operator=(const struct std::hash &) --> struct std::hash &", pybind11::return_value_policy::automatic, pybind11::arg("")); } { // std::hash file:bits/basic_string.h line:3044 pybind11::class_, std::shared_ptr>> cl(M("std"), "hash_std_string_t", ""); cl.def( pybind11::init( [](){ return new std::hash(); } ) ); - cl.def("__call__", (unsigned long (std::hash::*)(const std::string &) const) &std::hash::operator(), "C++: std::hash::operator()(const std::string &) const --> unsigned long", pybind11::arg("__s")); + cl.def("__call__", (std::size_t (std::hash::*)(const std::string &) const) &std::hash::operator(), "C++: std::hash::operator()(const std::string &) const --> std::size_t", pybind11::arg("__s")); } { // std::multimap file:bits/stl_multimap.h line:95 pybind11::class_, std::shared_ptr>> cl(M("std"), "multimap_float_int_t", ""); diff --git a/test/T42.stl.names.multimap.ref b/test/T42.stl.names.multimap.ref.cpp similarity index 99% rename from test/T42.stl.names.multimap.ref rename to test/T42.stl.names.multimap.ref.cpp index f0f7ea06..c1b06ad6 100644 --- a/test/T42.stl.names.multimap.ref +++ b/test/T42.stl.names.multimap.ref.cpp @@ -62,7 +62,7 @@ void bind_std_functional_hash(std::function< pybind11::module &(std::string cons pybind11::class_, std::shared_ptr>> cl(M("std"), "hash_float_t", ""); cl.def( pybind11::init( [](){ return new std::hash(); } ) ); cl.def( pybind11::init( [](std::hash const &o){ return new std::hash(o); } ) ); - cl.def("__call__", (unsigned long (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> unsigned long", pybind11::arg("__val")); + cl.def("__call__", (std::size_t (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> std::size_t", pybind11::arg("__val")); cl.def("assign", (struct std::hash & (std::hash::*)(const struct std::hash &)) &std::hash::operator=, "C++: std::hash::operator=(const struct std::hash &) --> struct std::hash &", pybind11::return_value_policy::automatic, pybind11::arg("")); } { // std::multimap file:bits/stl_multimap.h line:95 diff --git a/test/T42.stl.names.multiset.ref b/test/T42.stl.names.multiset.ref.cpp similarity index 98% rename from test/T42.stl.names.multiset.ref rename to test/T42.stl.names.multiset.ref.cpp index f8a7e383..e57161e4 100644 --- a/test/T42.stl.names.multiset.ref +++ b/test/T42.stl.names.multiset.ref.cpp @@ -61,7 +61,7 @@ void bind_std_functional_hash(std::function< pybind11::module &(std::string cons pybind11::class_, std::shared_ptr>> cl(M("std"), "hash_float_t", ""); cl.def( pybind11::init( [](){ return new std::hash(); } ) ); cl.def( pybind11::init( [](std::hash const &o){ return new std::hash(o); } ) ); - cl.def("__call__", (unsigned long (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> unsigned long", pybind11::arg("__val")); + cl.def("__call__", (std::size_t (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> std::size_t", pybind11::arg("__val")); cl.def("assign", (struct std::hash & (std::hash::*)(const struct std::hash &)) &std::hash::operator=, "C++: std::hash::operator=(const struct std::hash &) --> struct std::hash &", pybind11::return_value_policy::automatic, pybind11::arg("")); } { // std::multiset file:bits/stl_multiset.h line:92 diff --git a/test/T42.stl.names.ref b/test/T42.stl.names.ref.cpp similarity index 100% rename from test/T42.stl.names.ref rename to test/T42.stl.names.ref.cpp diff --git a/test/T42.stl.names.set.ref b/test/T42.stl.names.set.ref.cpp similarity index 99% rename from test/T42.stl.names.set.ref rename to test/T42.stl.names.set.ref.cpp index 62a9cb3d..37af8775 100644 --- a/test/T42.stl.names.set.ref +++ b/test/T42.stl.names.set.ref.cpp @@ -61,7 +61,7 @@ void bind_std_functional_hash(std::function< pybind11::module &(std::string cons pybind11::class_, std::shared_ptr>> cl(M("std"), "hash_float_t", ""); cl.def( pybind11::init( [](){ return new std::hash(); } ) ); cl.def( pybind11::init( [](std::hash const &o){ return new std::hash(o); } ) ); - cl.def("__call__", (unsigned long (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> unsigned long", pybind11::arg("__val")); + cl.def("__call__", (std::size_t (std::hash::*)(float) const) &std::hash::operator(), "C++: std::hash::operator()(float) const --> std::size_t", pybind11::arg("__val")); cl.def("assign", (struct std::hash & (std::hash::*)(const struct std::hash &)) &std::hash::operator=, "C++: std::hash::operator=(const struct std::hash &) --> struct std::hash &", pybind11::return_value_policy::automatic, pybind11::arg("")); } { // std::set file:bits/stl_set.h line:90 diff --git a/test/T43.stl.pybind11_include_stl.ref b/test/T43.stl.pybind11_include_stl.ref.cpp similarity index 100% rename from test/T43.stl.pybind11_include_stl.ref rename to test/T43.stl.pybind11_include_stl.ref.cpp diff --git a/test/T50.add_on_binder.config b/test/T50.add_on_binder.config new file mode 100644 index 00000000..6981e2ab --- /dev/null +++ b/test/T50.add_on_binder.config @@ -0,0 +1 @@ ++add_on_binder Matrix details::matrix_add_on_binder diff --git a/test/T50.add_on_binder.hpp b/test/T50.add_on_binder.hpp new file mode 100644 index 00000000..08b68d0b --- /dev/null +++ b/test/T50.add_on_binder.hpp @@ -0,0 +1,27 @@ +// -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*- +// vi: set ts=2 noet: +// +// Copyright (c) 2023 Sergey Lyskov +// +// All rights reserved. Use of this source code is governed by a +// MIT license that can be found in the LICENSE file. + +/// @file binder/test/T50.add_on_binder +/// @brief Binder self-test file. +/// @author Sergey Lyskov + + +#pragma once + + +template struct Matrix {}; +template class Matrix; + +namespace details { + +template +void matrix_add_on_binder(C &) +{ +} + +} // namespace details diff --git a/test/T50.add_on_binder.ref.cpp b/test/T50.add_on_binder.ref.cpp new file mode 100644 index 00000000..46852dd5 --- /dev/null +++ b/test/T50.add_on_binder.ref.cpp @@ -0,0 +1,77 @@ +// File: T50_add_on_binder.cpp +#include // Matrix +#include // __str__ + +#include +#include +#include + +#ifndef BINDER_PYBIND11_TYPE_CASTER + #define BINDER_PYBIND11_TYPE_CASTER + PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) + PYBIND11_DECLARE_HOLDER_TYPE(T, T*) + PYBIND11_MAKE_OPAQUE(std::shared_ptr) +#endif + +void bind_T50_add_on_binder(std::function< pybind11::module &(std::string const &namespace_) > &M) +{ + { // Matrix file:T50.add_on_binder.hpp line:18 + pybind11::class_, std::shared_ptr>> cl(M(""), "Matrix_int_t", ""); + cl.def( pybind11::init( [](){ return new Matrix(); } ) ); + + details::matrix_add_on_binder(cl); + } +} + + +#include +#include +#include +#include +#include +#include + +#include + +typedef std::function< pybind11::module & (std::string const &) > ModuleGetter; + +void bind_T50_add_on_binder(std::function< pybind11::module &(std::string const &namespace_) > &M); + + +PYBIND11_MODULE(T50_add_on_binder, root_module) { + root_module.doc() = "T50_add_on_binder module"; + + std::map modules; + ModuleGetter M = [&](std::string const &namespace_) -> pybind11::module & { + auto it = modules.find(namespace_); + if( it == modules.end() ) throw std::runtime_error("Attempt to access pybind11::module for namespace " + namespace_ + " before it was created!!!"); + return it->second; + }; + + modules[""] = root_module; + + static std::vector const reserved_python_words {"nonlocal", "global", }; + + auto mangle_namespace_name( + [](std::string const &ns) -> std::string { + if ( std::find(reserved_python_words.begin(), reserved_python_words.end(), ns) == reserved_python_words.end() ) return ns; + else return ns+'_'; + } + ); + + std::vector< std::pair > sub_modules { + }; + for(auto &p : sub_modules ) modules[p.first.size() ? p.first+"::"+p.second : p.second] = modules[p.first].def_submodule( mangle_namespace_name(p.second).c_str(), ("Bindings for " + p.first + "::" + p.second + " namespace").c_str() ); + + //pybind11::class_>(M(""), "_encapsulated_data_"); + + bind_T50_add_on_binder(M); + +} + +// Source list file: TEST/T50_add_on_binder.sources +// T50_add_on_binder.cpp +// T50_add_on_binder.cpp + +// Modules list file: TEST/T50_add_on_binder.modules +// diff --git a/test/T50.namespace_binder.ref b/test/T50.namespace_binder.ref.cpp similarity index 100% rename from test/T50.namespace_binder.ref rename to test/T50.namespace_binder.ref.cpp diff --git a/test/T60.custom_shared.ref b/test/T60.custom_shared.ref.cpp similarity index 100% rename from test/T60.custom_shared.ref rename to test/T60.custom_shared.ref.cpp diff --git a/test/T60.pybind11.ref b/test/T60.pybind11.ref.cpp similarity index 100% rename from test/T60.pybind11.ref rename to test/T60.pybind11.ref.cpp diff --git a/test/T70.module_local.ref b/test/T70.module_local.ref.cpp similarity index 100% rename from test/T70.module_local.ref rename to test/T70.module_local.ref.cpp diff --git a/test/T70.options.config b/test/T70.options.config index 4b7e6bda..38d09438 100644 --- a/test/T70.options.config +++ b/test/T70.options.config @@ -1,3 +1,5 @@ ++prefix_for_static_member_functions static_ + +namespace aaaa -namespace aaaa::bbbb diff --git a/test/T70.options.hpp b/test/T70.options.hpp index 68b4a75e..06e0112f 100644 --- a/test/T70.options.hpp +++ b/test/T70.options.hpp @@ -10,7 +10,12 @@ namespace aaaa { -struct AAAA {}; +struct AAAA +{ + void foo() {} + static void foo(int) {} +}; + void foo_aaaa() {} enum E1 { E1_V0, E1_V1 }; diff --git a/test/T70.options.ref b/test/T70.options.ref.cpp similarity index 89% rename from test/T70.options.ref rename to test/T70.options.ref.cpp index 09470cfb..2355ed95 100644 --- a/test/T70.options.ref +++ b/test/T70.options.ref.cpp @@ -20,11 +20,13 @@ void bind_T70_options(std::function< pybind11::module &(std::string const &names { // aaaa::AAAA file:T70.options.hpp line:13 pybind11::class_> cl(M("aaaa"), "AAAA", ""); cl.def( pybind11::init( [](){ return new aaaa::AAAA(); } ) ); + cl.def("foo", (void (aaaa::AAAA::*)()) &aaaa::AAAA::foo, "C++: aaaa::AAAA::foo() --> void"); + cl.def_static("static_foo", (void (*)(int)) &aaaa::AAAA::foo, "C++: aaaa::AAAA::foo(int) --> void", pybind11::arg("")); } - // aaaa::foo_aaaa() file:T70.options.hpp line:14 + // aaaa::foo_aaaa() file:T70.options.hpp line:19 M("aaaa").def("foo_aaaa", (void (*)()) &aaaa::foo_aaaa, "C++: aaaa::foo_aaaa() --> void"); - // aaaa::E1 file:T70.options.hpp line:16 + // aaaa::E1 file:T70.options.hpp line:21 pybind11::enum_(M("aaaa"), "E1", pybind11::arithmetic(), "") .value("E1_V0", aaaa::E1_V0) .value("E1_V1", aaaa::E1_V1) @@ -53,11 +55,11 @@ void bind_T70_options(std::function< pybind11::module &(std::string const &names void bind_T70_options_1(std::function< pybind11::module &(std::string const &namespace_) > &M) { - { // aaaa::cccc::CCCC file:T70.options.hpp line:20 + { // aaaa::cccc::CCCC file:T70.options.hpp line:25 pybind11::class_> cl(M("aaaa::cccc"), "CCCC", ""); cl.def( pybind11::init( [](){ return new aaaa::cccc::CCCC(); } ) ); } - // aaaa::cccc::foo_CCCC() file:T70.options.hpp line:21 + // aaaa::cccc::foo_CCCC() file:T70.options.hpp line:26 M("aaaa::cccc").def("foo_CCCC", (void (*)()) &aaaa::cccc::foo_CCCC, "C++: aaaa::cccc::foo_CCCC() --> void"); } @@ -81,11 +83,11 @@ void bind_T70_options_1(std::function< pybind11::module &(std::string const &nam void bind_T70_options_2(std::function< pybind11::module &(std::string const &namespace_) > &M) { - { // aaaa::bbbb::BBBB file:T70.options.hpp line:28 + { // aaaa::bbbb::BBBB file:T70.options.hpp line:33 pybind11::class_> cl(M("aaaa::bbbb"), "BBBB", ""); cl.def( pybind11::init( [](){ return new aaaa::bbbb::BBBB(); } ) ); } - // aaaa::bbbb::foo_bbbb() file:T70.options.hpp line:29 + // aaaa::bbbb::foo_bbbb() file:T70.options.hpp line:34 M("aaaa::bbbb").def("foo_bbbb", (void (*)()) &aaaa::bbbb::foo_bbbb, "C++: aaaa::bbbb::foo_bbbb() --> void"); } diff --git a/test/T71.module_local.ref b/test/T71.module_local.ref.cpp similarity index 100% rename from test/T71.module_local.ref rename to test/T71.module_local.ref.cpp diff --git a/test/T80.custom_trampoline.ref b/test/T80.custom_trampoline.ref.cpp similarity index 100% rename from test/T80.custom_trampoline.ref rename to test/T80.custom_trampoline.ref.cpp diff --git a/test/T81.custom_trampoline_with_args.ref b/test/T81.custom_trampoline_with_args.ref.cpp similarity index 100% rename from test/T81.custom_trampoline_with_args.ref rename to test/T81.custom_trampoline_with_args.ref.cpp diff --git a/test/self-test.py b/test/self-test.py index 49a6d293..f363207a 100755 --- a/test/self-test.py +++ b/test/self-test.py @@ -93,7 +93,7 @@ def run_test(test_path, build_dir): command_line = "cd {build_dir} && python2.7 -c 'import {root_module}'".format(root_module=root_module, build_dir=build_dir) execute('{} Testing imports...'.format(test), command_line); - ref = source_dir + '/' + test_name + '.ref' + ref = source_dir + '/' + test_name + '.ref.cpp' new = build_dir + '/' + root_module + '.cpp' command_line = 'diff {ref} {new}'.format(**vars())