Amey Narkhede
Amey Narkhede

Reputation: 13

Wrapping variadic templates in pybind11

I'm writing python bindings for glog like library which uses macro and has cout like syntax for logging. LOG(LEVEL)<<" "<<" ".... So I'm using this function to call the macro

    template <typename Arg, typename... Args>
    void log(auto level, Arg&& arg, Args&&... args)
    {
        std::stringstream out;
        out << std::forward<Arg>(arg);
        using expander = int[];
        (void)expander{0, (void(out << ' ' << std::forward<Args>(args)), 0)...};
        LOG(level) << out.str();
    }

So in order to wrap this function for pybind11 module I need to explicitly specify template type. Is there any possible workaround or way to bind this function using pybind11? I'm also open to use other libraries like boost.python or even cython if its possible.

Upvotes: 1

Views: 1085

Answers (1)

Wim Lavrijsen
Wim Lavrijsen

Reputation: 3788

Mixing templates and Python is best done at run-time to make sure you have all template instantiations that will actually be used. You can do that with cppyy (http://cppyy.org), which uses Cling (LLVM) underneath to instantiate the templates.

Using your example (with cerr replacing your LOG, the specific code for which you did not post):

import cppyy

# variadic template example; the code can also live in a header which is loaded 
# with "cppyy.include()"
cppyy.cppdef(r"""
    template <typename Arg, typename... Args>
    void log(int level, Arg&& arg, Args&&... args)
    {   
        std::stringstream out;
        out << std::forward<Arg>(arg);
        using expander = int[];
        (void)expander{0, (void(out << ' ' << std::forward<Args>(args)), 0)...};
        std::cerr << out.str() << '\n';
    }
""")

level = 1
cppyy.gbl.log(level, 1, "string", 3.14)

which has the expected out of:

1 string 3.14

Upvotes: 1

Related Questions