Функция экспорта шаблона - PullRequest
3 голосов
/ 18 марта 2011

Как правильно экспортировать шаблонную функцию из c ++ в python, используя boost.python? Вот код:

template<typename T>
T getValue(const std::string &key, const T &defaultValue = T()) {}

// Export into some python class:
class_<ConfigManager>(...)
.def("GetValue", getValue<int>)
.def("GetValue", getValue<float>)
.def("GetValue", getValue<std::string>);

И использование:

    print GetValue("width")
Boost.Python.ArgumentError: Python argument types in
    GetValue(ConfigManager, str)
did not match C++ signature:
    GetValue(ConfigManager {lvalue}, std::string, int)

Что не так?

Ответы [ 2 ]

5 голосов
/ 18 марта 2011

Вы должны прочитать соответствующую документацию Boost относительно аргументов по умолчанию.Я подведу итог ниже.


Проблема в том, что аргументы по умолчанию используются при вызове функций в C ++ .Избавьтесь от них, и вы увидите проблему с точки зрения Python:

// this function *must* be called with two parameters
template<typename T>
T getValue(const std::string &key, const T &defaultValue) {}

class_<ConfigManager>(...)
.def("GetValue", getValue<int>) // two arguments!
.def("GetValue", getValue<float>) // Python has no idea about the defaults,
.def("GetValue", getValue<std::string>); // they are a C++ feature for calling

Основная проблема заключается в том, что типы функций не несут информацию об аргументах по умолчанию.Итак, как мы можем имитировать это?По сути, при перегрузке:

template<typename T>
T getValue(const std::string &key, const T &defaultValue) {}

template<typename T>
T getValueDefault(const std::string &key)
{
    // default available in C++,
    // transitively available in Python
    return getValue(key);
}

class_<ConfigManager>(...)
.def("GetValue", getValue<int>) // two arguments
.def("GetValue", getValueDefault<int>) // one argument
// and so on

Сложность в обслуживании.К счастью, Boost делает это легко:

template<typename T>
T getValue(const std::string &key, const T &defaultValue) {}

// creates utility class x, which creates overloads of function y,
// with argument count as low as a and as high as b:
// BOOST_PYTHON_FUNCTION_OVERLOADS(x, y, a, b);

BOOST_PYTHON_FUNCTION_OVERLOADS(getValueIntOverloads, getValue<int>, 1, 2);

class_<ConfigManager>(...)
.def("GetValue", getValue<int>, getValueIntOverloads()) // one or two arguments

// and so on

Макрос также существует для членов класса.Это в документации, если что-то неясно.

0 голосов
/ 09 сентября 2016

Вы также можете добавить другой шаблон для своего класса, чтобы вам не приходилось писать / создавать экземпляры для каждого типа int / float.

template<typename LinksT>
class Base {
public:
  virtual ~Base()  {}
  virtual Base* x() = 0;
};

#include <boost/python.hpp>
using namespace boost::python;

template<typename LinksT>
class BaseWrap : public Base<LinksT>, public wrapper<Base<LinksT> > {
public:
  virtual Base<LinksT>* x() { return this->get_override("x")(); }
};

template<typename LinksT>
void export_virtualfunction()
{
    class_<BaseWrap<LinksT>, boost::noncopyable>("Base", no_init)
        .def("x", pure_virtual(&Base<LinksT>::x), return_internal_reference<>())
        ;
}

BOOST_PYTHON_MODULE(test_template_python)
{
    export_virtualfunction<int>();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...