1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
#ifndef WREPORT_PYTHON_METHODS_H
#define WREPORT_PYTHON_METHODS_H
#include "core.h"
#include <array>
namespace wreport {
namespace python {
/**
* Build a function docstring from its components.
*
* Returns a newly allocated string.
*/
std::string build_method_doc(const char* name, const char* signature, const char* returns, const char* summary, const char* doc);
/// Common infrastructure for all methods
template<typename Child>
struct BaseMethod
{
constexpr static const char* name = "TODO";
constexpr static const char* signature = "";
constexpr static const char* returns = nullptr;
constexpr static const char* summary = nullptr;
constexpr static const char* doc = nullptr;
static constexpr PyMethodDef def()
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
return PyMethodDef {const_cast<char*>(Child::name), (PyCFunction)Child::run, Child::flags, Child::doc};
#pragma GCC diagnostic pop
}
static std::string docstring()
{
return build_method_doc(Child::name, Child::signature, Child::returns, Child::summary, Child::doc);
}
};
/// Base implementation for a METH_NOARGS method
template<typename Child, typename IMPL>
struct MethNoargs : public BaseMethod<Child>
{
typedef IMPL Impl;
constexpr static int flags = METH_NOARGS;
static PyObject* run(Impl* self)
{
PyErr_Format(PyExc_NotImplementedError, "method %s is not implemented", Child::name);
return nullptr;
}
};
/// Base implementation for a METH_NOARGS class method
template<typename Child>
struct ClassMethNoargs : public BaseMethod<Child>
{
constexpr static int flags = METH_NOARGS | METH_CLASS;
static PyObject* run(PyTypeObject* cls)
{
PyErr_Format(PyExc_NotImplementedError, "method %s is not implemented", Child::name);
return nullptr;
}
};
/// Base implementation for a METH_VARARGS method
template<typename Child, typename IMPL>
struct MethVarargs : public BaseMethod<Child>
{
typedef IMPL Impl;
constexpr static int flags = METH_VARARGS;
static PyObject* run(Impl* self, PyObject* args)
{
PyErr_Format(PyExc_NotImplementedError, "method %s is not implemented", Child::name);
return nullptr;
}
};
/// Base implementation for a METH_KWARGS method
template<typename Child, typename IMPL>
struct MethKwargs : public BaseMethod<Child>
{
typedef IMPL Impl;
constexpr static int flags = METH_VARARGS | METH_KEYWORDS;
static PyObject* run(Impl* self, PyObject* args, PyObject* kw)
{
PyErr_Format(PyExc_NotImplementedError, "method %s is not implemented", Child::name);
return nullptr;
}
};
/// Base implementation for a METH_KWARGS class method
template<typename Child>
struct ClassMethKwargs : public BaseMethod<Child>
{
constexpr static int flags = METH_VARARGS | METH_KEYWORDS | METH_CLASS;
static PyObject* run(PyTypeObject* cls, PyObject* args, PyObject* kw)
{
PyErr_Format(PyExc_NotImplementedError, "method %s is not implemented", Child::name);
return nullptr;
}
};
template<typename... METHODS>
struct Methods
{
typedef std::array<std::string, sizeof...(METHODS)> Docstrings;
typedef std::array<PyMethodDef, sizeof...(METHODS) + 1> Defs;
Docstrings docstrings;
Defs m_defs;
Methods() :
docstrings({METHODS::docstring()...}),
m_defs({METHODS::def()..., PyMethodDef()})
{
for (unsigned i = 0; i < m_defs.size() - 1; ++i)
m_defs[i].ml_doc = docstrings[i].c_str();
}
PyMethodDef* as_py()
{
return const_cast<PyMethodDef*>(m_defs.data());
}
};
template<>
struct Methods<>
{
PyMethodDef* as_py() { return 0; }
};
}
}
#endif
|