Оборачиваем вариативные шаблоны в pybind11

Я пишу привязки python для glog, такой как библиотека, которая использует макрос и имеет синтаксис cout для ведения журнала. LOG(LEVEL)<<" "<<" ".... Итак, я использую эту функцию для вызова макроса

    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();
    }

Итак, чтобы обернуть эту функцию для модуля pybind11, мне нужно явно указать тип шаблона. Есть ли какой-либо возможный обходной путь или способ связать эту функцию с помощью pybind11? Я также открыт для использования других библиотек, таких как boost.python или даже cython, если это возможно.


person Amey Narkhede    schedule 12.12.2018    source источник


Ответы (1)


Смешивание шаблонов и Python лучше всего выполнять во время выполнения, чтобы убедиться, что у вас есть все экземпляры шаблонов, которые действительно будут использоваться. Вы можете сделать это с помощью cppyy (http://cppyy.org), который использует Cling (LLVM) для создания экземпляра шаблоны.

Используя ваш пример (с cerr заменой вашего LOG, конкретного кода, для которого вы не опубликовали):

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)

который имеет ожидаемое из:

1 string 3.14
person Wim Lavrijsen    schedule 07.11.2019