Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 42 additions & 20 deletions source/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,30 +93,48 @@ using ModuleGetter = std::function< pybind11::module & (std::string const &) >;

{1}

static std::vector<std::string> const reserved_python_words{{
"nonlocal",
"global",
}};
std::string mangle_namespace_name(std::string const &ns) {{
if( std::find(reserved_python_words.begin(), reserved_python_words.end(), ns) == reserved_python_words.end() ) return ns;
return ns + '_';
}}

void makeSubmodules(const std::vector<std::string> &moduleNames, std::map <std::string, pybind11::module> &modules) {{
std::string prevNamespace = "";
std::string curNamespace = "";
for (const auto &curMod : moduleNames) {{
if (curNamespace.size() > 0)
curNamespace += "::"; // don't add :: to the start
const auto mangledMod = mangle_namespace_name(curMod);
curNamespace += mangledMod;
if (modules.count(curNamespace) == 0) {{
modules[curNamespace] = modules[prevNamespace].def_submodule(mangledMod.c_str(), ("Bindings for " + curNamespace + " namespace").c_str());
}}
prevNamespace = curNamespace;
}}
}}


PYBIND11_MODULE({2}, root_module) {{
root_module.doc() = "{2} module";

std::map <std::string, pybind11::module> modules;
ModuleGetter M = [&](std::string const &namespace_) -> pybind11::module & {{
auto it = modules.find(namespace_);
auto it = modules.find(mangle_namespace_name(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<std::string> 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;
return ns+'_';
}}
);

std::vector< std::pair<std::string, std::string> > sub_modules {{
std::vector< std::vector<std::string> > sub_modules {{
{3} }};
for(auto &p : sub_modules ) modules[ p.first.empty() ? p.second : p.first+"::"+p.second ] = modules[p.first].def_submodule( mangle_namespace_name(p.second).c_str(), ("Bindings for " + p.first + "::" + p.second + " namespace").c_str() );
for(auto &p : sub_modules ) {{
makeSubmodules(p, modules);
}}

//pybind11::class_<std::shared_ptr<void>>(M(""), "_encapsulated_data_");

Expand Down Expand Up @@ -213,22 +231,20 @@ void Context::add_to_binded(CXXRecordDecl const *C)
/// examine binded objects and recursivly create all nested namespaces
std::set<string> Context::create_all_nested_namespaces()
{
vector<string> namespaces;
std::set<string> namespaces;

for( auto &b : binders ) {
if( b->code().size() ) {
string ns = namespace_from_named_decl(b->named_decl());

while( ns.size() ) {
namespaces.push_back(ns);
namespaces.insert(ns);
ns = base_namespace(ns);
}
}
}

std::set<string> s(namespaces.begin(), namespaces.end());

return s;
return namespaces;
}

std::string Context::module_variable_name(std::string const &namespace_)
Expand Down Expand Up @@ -454,9 +470,15 @@ void Context::generate(Config const &config)
string namespace_pairs;
std::set<string> namespaces = create_all_nested_namespaces();
for( auto &n : namespaces ) {
if( n.size() ) namespace_pairs += "\t\t{{\"{}\", \"{}\"}},\n"_format(base_namespace(n), last_namespace(n));
modules += n;
modules += ' ';
if( n.size() ) {
const auto curMods = split(n, "::");
namespace_pairs += "\t\t{";
for( size_t i = 0; i < curMods.size(); i++ ) {
namespace_pairs += "\"" + curMods[i] + "\"";
if( i != curMods.size() - 1 ) namespace_pairs += ", ";
}
namespace_pairs += "},\n";
}
}
replace(modules, "::", ".");

Expand Down
30 changes: 13 additions & 17 deletions source/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,21 @@ namespace binder {


/// Split string using given separator
vector<string> split(string const &buffer, string const &separator)
{
string line;
vector<string> lines;

for( uint i = 0; i < buffer.size(); ++i ) {
if( buffer.compare(i, separator.size(), separator) ) line.push_back(buffer[i]);
else {
lines.push_back(line);
line.resize(0);
}
}

if( line.size() ) lines.push_back(line);

return lines;
std::vector<std::string> split(const std::string &s, const std::string &delimiter) {
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
std::string token;
std::vector<std::string> res;

while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) {
token = s.substr (pos_start, pos_end - pos_start);
pos_start = pos_end + delim_len;
res.push_back (token);
}

res.push_back (s.substr (pos_start));
return res;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please say a few words why do you want to rewrite this function? Thanks,

}


/// Replace all occurrences of string
void replace_reverse(string &r, string const &from, string const &to)
{
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ set( binder_tests
T42.stl.names.multiset
T43.stl.pybind11_include_stl
T50.namespace_binder
T51.nested_namespace
T60.custom_shared
)
if (pybind11_VERSION VERSION_LESS 2.5.99)
Expand Down
15 changes: 15 additions & 0 deletions test/T51.nested_namespace.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

#ifndef _INCLUDED_T51_NESTED_NAMESPACES_
#define _INCLUDED_T51_NESTED_NAMESPACES_

namespace aaaa::bbbb::cccc {
void foo_aaaa_bbbb_cccc() {}
namespace dddd{
void bar_aaaa_bbbb_cccc_dddd() {}
}
namespace eeee {
void baz_aaaa_bbbb_cccc_eeee() {}
}
}

#endif // _INCLUDED_T51_NESTED_NAMESPACES_
150 changes: 150 additions & 0 deletions test/T51.nested_namespace.ref.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// File: T51_nested_namespace.cpp
#include <T51.nested_namespace.hpp> // aaaa::bbbb::cccc::foo_aaaa_bbbb_cccc

#include <functional>
#include <pybind11/pybind11.h>
#include <string>

#ifndef BINDER_PYBIND11_TYPE_CASTER
#define BINDER_PYBIND11_TYPE_CASTER
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>, false)
PYBIND11_DECLARE_HOLDER_TYPE(T, T*, false)
PYBIND11_MAKE_OPAQUE(std::shared_ptr<void>)
#endif

void bind_T51_nested_namespace(std::function< pybind11::module &(std::string const &namespace_) > &M)
{
// aaaa::bbbb::cccc::foo_aaaa_bbbb_cccc() file:T51.nested_namespace.hpp line:6
M("aaaa::bbbb::cccc").def("foo_aaaa_bbbb_cccc", (void (*)()) &aaaa::bbbb::cccc::foo_aaaa_bbbb_cccc, "C++: aaaa::bbbb::cccc::foo_aaaa_bbbb_cccc() --> void");

}


// File: T51_nested_namespace_1.cpp
#include <T51.nested_namespace.hpp> // aaaa::bbbb::cccc::dddd::bar_aaaa_bbbb_cccc_dddd

#include <functional>
#include <pybind11/pybind11.h>
#include <string>

#ifndef BINDER_PYBIND11_TYPE_CASTER
#define BINDER_PYBIND11_TYPE_CASTER
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>, false)
PYBIND11_DECLARE_HOLDER_TYPE(T, T*, false)
PYBIND11_MAKE_OPAQUE(std::shared_ptr<void>)
#endif

void bind_T51_nested_namespace_1(std::function< pybind11::module &(std::string const &namespace_) > &M)
{
// aaaa::bbbb::cccc::dddd::bar_aaaa_bbbb_cccc_dddd() file:T51.nested_namespace.hpp line:8
M("aaaa::bbbb::cccc::dddd").def("bar_aaaa_bbbb_cccc_dddd", (void (*)()) &aaaa::bbbb::cccc::dddd::bar_aaaa_bbbb_cccc_dddd, "C++: aaaa::bbbb::cccc::dddd::bar_aaaa_bbbb_cccc_dddd() --> void");

}


// File: T51_nested_namespace_2.cpp
#include <T51.nested_namespace.hpp> // aaaa::bbbb::cccc::eeee::baz_aaaa_bbbb_cccc_eeee

#include <functional>
#include <pybind11/pybind11.h>
#include <string>

#ifndef BINDER_PYBIND11_TYPE_CASTER
#define BINDER_PYBIND11_TYPE_CASTER
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>, false)
PYBIND11_DECLARE_HOLDER_TYPE(T, T*, false)
PYBIND11_MAKE_OPAQUE(std::shared_ptr<void>)
#endif

void bind_T51_nested_namespace_2(std::function< pybind11::module &(std::string const &namespace_) > &M)
{
// aaaa::bbbb::cccc::eeee::baz_aaaa_bbbb_cccc_eeee() file:T51.nested_namespace.hpp line:11
M("aaaa::bbbb::cccc::eeee").def("baz_aaaa_bbbb_cccc_eeee", (void (*)()) &aaaa::bbbb::cccc::eeee::baz_aaaa_bbbb_cccc_eeee, "C++: aaaa::bbbb::cccc::eeee::baz_aaaa_bbbb_cccc_eeee() --> void");

}


#include <map>
#include <algorithm>
#include <functional>
#include <memory>
#include <stdexcept>
#include <string>
#include <iostream>

#include <pybind11/pybind11.h>

using ModuleGetter = std::function< pybind11::module & (std::string const &) >;

void bind_T51_nested_namespace(std::function< pybind11::module &(std::string const &namespace_) > &M);
void bind_T51_nested_namespace_1(std::function< pybind11::module &(std::string const &namespace_) > &M);
void bind_T51_nested_namespace_2(std::function< pybind11::module &(std::string const &namespace_) > &M);


static std::vector<std::string> const reserved_python_words{
"nonlocal",
"global",
};
std::string mangle_namespace_name(std::string const &ns) {
if( std::find(reserved_python_words.begin(), reserved_python_words.end(), ns) == reserved_python_words.end() ) return ns;
return ns + '_';
}

void makeSubmodules(const std::vector<std::string> &moduleNames, std::map <std::string, pybind11::module> &modules) {
std::string prevNamespace = "";
std::string curNamespace = "";
for (const auto &curMod : moduleNames) {
std::cout << "making: " << curMod << std::endl;
if (curNamespace.size() > 0)
curNamespace += "::"; // don't add :: to the start
const auto mangledMod = mangle_namespace_name(curMod);
std::cout << "mangled: " << mangledMod << std::endl;
curNamespace += mangledMod;
if (modules.count(curNamespace) == 0) {
std::cout << "defining namespace " << curNamespace << " in " << prevNamespace << std::endl;
modules[curNamespace] = modules[prevNamespace].def_submodule(mangledMod.c_str(), ("Bindings for " + curNamespace + " namespace").c_str());
}
prevNamespace = curNamespace;
}
}


PYBIND11_MODULE(T51_nested_namespace, root_module) {
root_module.doc() = "T51_nested_namespace module";

std::map <std::string, pybind11::module> modules;
ModuleGetter M = [&](std::string const &namespace_) -> pybind11::module & {
auto it = modules.find(mangle_namespace_name(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;

std::vector< std::vector<std::string> > sub_modules {
{"aaaa"},
{"aaaa", "bbbb"},
{"aaaa", "bbbb", "cccc"},
{"aaaa", "bbbb", "cccc", "dddd"},
{"aaaa", "bbbb", "cccc", "eeee"},
};
for(auto &p : sub_modules ) {
makeSubmodules(p, modules);
}

//pybind11::class_<std::shared_ptr<void>>(M(""), "_encapsulated_data_");

bind_T51_nested_namespace(M);
bind_T51_nested_namespace_1(M);
bind_T51_nested_namespace_2(M);

}

// Source list file: /home/matt/workspace/binder/build/test//T51_nested_namespace.sources
// T51_nested_namespace.cpp
// T51_nested_namespace.cpp
// T51_nested_namespace_1.cpp
// T51_nested_namespace_2.cpp

// Modules list file: /home/matt/workspace/binder/build/test//T51_nested_namespace.modules
//
Loading