Files
ortools-clone/ortools/base/python-swig.h

365 lines
10 KiB
C
Raw Normal View History

// Copyright 2010-2021 Google LLC
2014-07-09 09:58:03 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2013-12-05 17:11:01 +00:00
// Static part of SWIG-generated C++ wrapper for Python (_module_name.cc).
//
// This file should only be included in base.i inside Python-specific part:
2013-12-05 17:11:01 +00:00
// #ifdef SWIGPYTHON
// %{
// #include "ortools/base/swig/python-swig.cc"
2013-12-05 17:11:01 +00:00
// %}
// #endif
// It has no XXX_H_ guard because SWIG protects all %include'd files to be used
// only once.
2014-07-09 09:58:03 +00:00
#ifndef OR_TOOLS_BASE_PYTHON_SWIG_H_
#define OR_TOOLS_BASE_PYTHON_SWIG_H_
2020-10-22 23:36:58 +02:00
#if PY_VERSION_HEX >= 0x03030000 // Py3.3+
2013-12-05 17:11:01 +00:00
// Use Py3 unicode str() type for C++ strings.
#ifdef PyString_FromStringAndSize
#undef PyString_FromStringAndSize
#endif
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#ifdef PyString_AsString
#undef PyString_AsString
#endif
#define PyString_AsString PyUnicode_AsUTF8
#ifdef PyString_AsStringAndSize
#undef PyString_AsStringAndSize
#endif
2020-10-29 14:25:39 +01:00
static inline int PyString_AsStringAndSize(PyObject* obj, char** buf,
Py_ssize_t* psize) {
2013-12-05 17:11:01 +00:00
if (PyUnicode_Check(obj)) {
2020-10-29 14:25:39 +01:00
*buf = const_cast<char*>(PyUnicode_AsUTF8AndSize(obj, psize));
2022-03-03 14:08:37 +01:00
return *buf == nullptr ? -1 : 0;
2013-12-05 17:11:01 +00:00
} else if (PyBytes_Check(obj)) {
return PyBytes_AsStringAndSize(obj, buf, psize);
}
PyErr_SetString(PyExc_TypeError, "Expecting str or bytes");
return -1;
}
2020-10-22 23:36:58 +02:00
#endif // Py3.3+
2013-12-05 17:11:01 +00:00
2020-10-22 23:36:58 +02:00
template <class T>
2020-10-29 14:25:39 +01:00
inline bool PyObjAs(PyObject* pystr, T* cstr) {
2020-10-22 23:36:58 +02:00
T::undefined; // You need to define specialization PyObjAs<T>
2013-12-05 17:11:01 +00:00
}
2020-10-22 23:36:58 +02:00
template <class T>
2020-10-29 14:25:39 +01:00
inline PyObject* PyObjFrom(const T& c) {
2020-10-22 23:36:58 +02:00
T::undefined; // You need to define specialization PyObjFrom<T>
2013-12-05 17:11:01 +00:00
}
#ifdef HAS_GLOBAL_STRING
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline bool PyObjAs(PyObject* pystr, ::std::string* cstr) {
char* buf;
2013-12-05 17:11:01 +00:00
Py_ssize_t len;
#if PY_VERSION_HEX >= 0x03030000
if (PyUnicode_Check(pystr)) {
buf = PyUnicode_AsUTF8AndSize(pystr, &len);
2020-10-22 23:36:58 +02:00
if (!buf) return false;
} else // NOLINT
2013-12-05 17:11:01 +00:00
#endif
if (PyBytes_AsStringAndSize(pystr, &buf, &len) == -1)
return false;
2020-10-22 23:36:58 +02:00
if (cstr) cstr->assign(buf, len);
2013-12-05 17:11:01 +00:00
return true;
}
#endif
2020-10-22 23:36:58 +02:00
template <class T>
2020-10-29 14:25:39 +01:00
inline bool PyObjAs(PyObject* pystr, std::string* cstr) {
char* buf;
2013-12-05 17:11:01 +00:00
Py_ssize_t len;
#if PY_VERSION_HEX >= 0x03030000
if (PyUnicode_Check(pystr)) {
2020-10-29 14:25:39 +01:00
buf = const_cast<char*>(PyUnicode_AsUTF8AndSize(pystr, &len));
2020-10-22 23:36:58 +02:00
if (!buf) return false;
} else // NOLINT
2013-12-05 17:11:01 +00:00
#endif
if (PyBytes_AsStringAndSize(pystr, &buf, &len) == -1)
return false;
2020-10-22 23:36:58 +02:00
if (cstr) cstr->assign(buf, len);
2013-12-05 17:11:01 +00:00
return true;
}
#ifdef HAS_GLOBAL_STRING
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline PyObject* PyObjFrom(const ::std::string& c) {
2013-12-05 17:11:01 +00:00
return PyString_FromStringAndSize(c.data(), c.size());
}
#endif
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline PyObject* PyObjFrom(const std::string& c) {
2013-12-05 17:11:01 +00:00
return PyString_FromStringAndSize(c.data(), c.size());
}
// Do numeric specialization.
#include <limits>
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline bool PyObjAs(PyObject* py, int* c) {
2020-10-22 23:36:58 +02:00
long i = PyInt_AsLong(py); // NOLINT
if (i == -1 && PyErr_Occurred()) // TypeError or OverflowError.
return false; // Not a Python int.
2013-12-05 17:11:01 +00:00
if (i < std::numeric_limits<int>::min() ||
i > std::numeric_limits<int>::max())
2020-10-22 23:36:58 +02:00
return false; // Not C int.
if (c) *c = static_cast<int>(i);
2013-12-05 17:11:01 +00:00
return true;
}
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline bool PyObjAs(PyObject* py, unsigned int* c) {
2020-10-22 23:36:58 +02:00
long i = PyInt_AsLong(py); // NOLINT
if (i == -1 && PyErr_Occurred()) return false; // Not a Python int.
if (i < 0 || i > std::numeric_limits<unsigned int>::max()) return false;
if (c) *c = static_cast<unsigned int>(i);
2013-12-05 17:11:01 +00:00
return true;
}
2020-10-22 23:36:58 +02:00
template <>
2021-04-01 12:13:35 +02:00
inline bool PyObjAs(PyObject* py, int64_t* c) { // NOLINT
int64_t i; // NOLINT
2013-12-05 17:11:01 +00:00
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(py)) {
i = PyInt_AsLong(py);
} else {
2020-10-22 23:36:58 +02:00
if (!PyLong_Check(py)) return false; // Not a Python long.
2013-12-05 17:11:01 +00:00
#else
{
#endif
i = PyLong_AsLongLong(py);
2020-10-22 23:36:58 +02:00
if (i == -1 && PyErr_Occurred()) return false; // Not a C long long.
2013-12-05 17:11:01 +00:00
}
2020-10-22 23:36:58 +02:00
if (c) *c = i;
2013-12-05 17:11:01 +00:00
return true;
}
2020-10-22 23:36:58 +02:00
template <>
2021-04-01 12:13:35 +02:00
inline bool PyObjAs(PyObject* py, uint64_t* c) { // NOLINT
uint64_t i; // NOLINT
2013-12-05 17:11:01 +00:00
#if PY_MAJOR_VERSION < 3
2014-07-09 09:58:03 +00:00
if (PyInt_Check(py)) {
2013-12-05 17:11:01 +00:00
i = PyInt_AsUnsignedLongLongMask(py);
2020-10-22 23:36:58 +02:00
} else // NOLINT
2013-12-05 17:11:01 +00:00
#endif
2020-10-22 23:36:58 +02:00
{
if (!PyLong_Check(py)) return false; // Not a Python long.
2013-12-05 17:11:01 +00:00
i = PyLong_AsUnsignedLongLong(py);
2021-04-01 12:13:35 +02:00
if (i == (uint64_t)-1 && PyErr_Occurred()) // NOLINT
return false;
2013-12-05 17:11:01 +00:00
}
2020-10-22 23:36:58 +02:00
if (c) *c = i;
2013-12-05 17:11:01 +00:00
return true;
}
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline bool PyObjAs(PyObject* py, double* c) {
2013-12-05 17:11:01 +00:00
double d;
if (PyFloat_Check(py)) {
d = PyFloat_AsDouble(py);
#if PY_MAJOR_VERSION < 3
} else if (PyInt_Check(py)) {
d = PyInt_AsLong(py);
} else if (!PyLong_Check(py)) {
2020-10-22 23:36:58 +02:00
return false; // float or int/long expected
2013-12-05 17:11:01 +00:00
#endif
} else {
d = PyLong_AsDouble(py);
if (d == -1.0 && PyErr_Occurred()) {
2020-10-22 23:36:58 +02:00
return false; // Overflow (or TypeError for PY3)
2013-12-05 17:11:01 +00:00
}
}
2020-10-22 23:36:58 +02:00
if (c) *c = d;
2013-12-05 17:11:01 +00:00
return true;
}
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline PyObject* PyObjFrom(const double& c) {
2013-12-05 17:11:01 +00:00
return PyFloat_FromDouble(c);
}
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline bool PyObjAs(PyObject* py, float* c) {
2013-12-05 17:11:01 +00:00
double d;
2020-10-22 23:36:58 +02:00
if (!PyObjAs(py, &d)) return false;
if (c) *c = static_cast<float>(d);
2013-12-05 17:11:01 +00:00
return true;
}
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline PyObject* PyObjFrom(const float& c) {
2013-12-05 17:11:01 +00:00
return PyFloat_FromDouble(c);
}
2020-10-22 23:36:58 +02:00
template <>
2020-10-29 14:25:39 +01:00
inline bool PyObjAs(PyObject* py, bool* c) {
2020-10-22 23:36:58 +02:00
if (!PyBool_Check(py)) return false; // Not a Python bool.
if (c) *c = PyObject_Not(py) ? false : true;
2013-12-05 17:11:01 +00:00
return true;
}
2020-10-29 14:25:39 +01:00
inline int SwigPyIntOrLong_Check(PyObject* o) {
2013-12-05 17:11:01 +00:00
return (PyLong_Check(o)
#if PY_MAJOR_VERSION <= 2
|| PyInt_Check(o)
#endif
2020-10-22 23:36:58 +02:00
); // NOLINT
2013-12-05 17:11:01 +00:00
}
inline int SwigString_Check(PyObject* o) { return PyUnicode_Check(o); }
2020-10-29 14:25:39 +01:00
inline PyObject* SwigString_FromString(const std::string& s) {
2014-01-08 12:01:58 +00:00
return PyString_FromStringAndSize(s.data(), s.size());
2013-12-05 17:11:01 +00:00
}
2020-10-29 14:25:39 +01:00
inline std::string SwigString_AsString(PyObject* o) {
2014-07-09 09:58:03 +00:00
return std::string(PyString_AsString(o));
}
2013-12-05 17:11:01 +00:00
// STL std::vector<T> for common types
2020-10-22 23:36:58 +02:00
namespace { // NOLINT
2013-12-05 17:11:01 +00:00
2020-10-22 23:36:58 +02:00
template <typename T>
struct vector_pusher {
2020-10-29 14:25:39 +01:00
typedef T* ptr;
static void push(std::vector<T>* o, ptr e) { o->push_back(*e); }
2013-12-05 17:11:01 +00:00
};
2020-10-22 23:36:58 +02:00
template <typename T>
2020-10-29 14:25:39 +01:00
struct vector_pusher<T*> {
typedef T* ptr;
static void push(std::vector<T*>* o, ptr e) { o->push_back(e); }
2013-12-05 17:11:01 +00:00
};
2020-10-22 23:36:58 +02:00
}; // namespace
2013-12-05 17:11:01 +00:00
template <class T>
2020-10-29 14:25:39 +01:00
inline bool vector_input_helper(PyObject* seq, std::vector<T>* out,
bool (*convert)(PyObject*, T* const)) {
2018-06-08 16:40:43 +02:00
PyObject *item, *it = PyObject_GetIter(seq);
2020-10-22 23:36:58 +02:00
if (!it) return false;
2013-12-05 17:11:01 +00:00
T elem;
while ((item = PyIter_Next(it))) {
bool success = convert(item, &elem);
Py_DECREF(item);
if (!success) {
Py_DECREF(it);
return false;
}
2020-10-22 23:36:58 +02:00
if (out) out->push_back(elem);
2013-12-05 17:11:01 +00:00
}
Py_DECREF(it);
return static_cast<bool>(!PyErr_Occurred());
}
template <class T>
2020-10-29 14:25:39 +01:00
inline bool vector_input_wrap_helper(PyObject* seq, std::vector<T>* out,
swig_type_info* swig_Tp_type) {
2018-06-08 16:40:43 +02:00
PyObject *item, *it = PyObject_GetIter(seq);
2013-12-05 17:11:01 +00:00
if (!it) {
PyErr_SetString(PyExc_TypeError, "sequence expected");
return false;
}
typename vector_pusher<T>::ptr elem;
while ((item = PyIter_Next(it))) {
2020-10-29 14:25:39 +01:00
if (SWIG_ConvertPtr(item, reinterpret_cast<void**>(&elem), swig_Tp_type,
2018-06-08 16:40:43 +02:00
0) == -1) {
2013-12-05 17:11:01 +00:00
Py_DECREF(it);
it = PyObject_Repr(item);
Py_DECREF(item);
2020-10-29 14:25:39 +01:00
const char* repr = it ? PyString_AsString(it) : "not";
2013-12-05 17:11:01 +00:00
PyErr_Format(PyExc_TypeError, "'%s' expected, %s found",
SWIG_TypePrettyName(swig_Tp_type), repr);
Py_XDECREF(it);
return false;
}
Py_DECREF(item);
2020-10-22 23:36:58 +02:00
if (out) vector_pusher<T>::push(out, elem);
2013-12-05 17:11:01 +00:00
}
Py_DECREF(it);
return true;
}
// Helper function for turning a C++ std::vector<T> (or any other instance that
// supports the std::vector<T>-like iterator interface) into a Python list of
// Ts.
// The converter function converts a C++ object of type const T or const T&
// into the corresponding Python object.
template <class T, class Converter>
2020-10-29 14:25:39 +01:00
inline PyObject* list_output_helper(const T* vec, Converter converter) {
2022-03-03 14:08:37 +01:00
if (vec == nullptr) Py_RETURN_NONE; // Return a nice out-of-band value.
2020-10-29 14:25:39 +01:00
PyObject* lst = PyList_New(vec->size());
2022-03-03 14:08:37 +01:00
if (lst == nullptr) return nullptr;
2013-12-05 17:11:01 +00:00
int i = 0;
for (typename T::const_reference pt : *vec) {
2020-10-29 14:25:39 +01:00
PyObject* obj = converter(pt);
2013-12-05 17:11:01 +00:00
if (!obj) {
Py_DECREF(lst);
2022-03-03 14:08:37 +01:00
return nullptr;
2013-12-05 17:11:01 +00:00
}
PyList_SET_ITEM(lst, i++, obj);
}
return lst;
}
2020-10-22 23:36:58 +02:00
template <class T>
struct OutConverter {
2020-10-29 14:25:39 +01:00
PyObject* operator()(const T x) const {
return SWIG_NewPointerObj((void*)x, type_, new_); // NOLINT
2013-12-05 17:11:01 +00:00
}
2020-10-29 14:25:39 +01:00
swig_type_info* type_;
2013-12-05 17:11:01 +00:00
int new_;
2020-10-29 14:25:39 +01:00
OutConverter(swig_type_info* type, int new_object)
2013-12-05 17:11:01 +00:00
: type_(type), new_(new_object) {}
};
template <class T, class TR>
2020-10-29 14:25:39 +01:00
inline PyObject* vector_output_helper(const std::vector<T>* vec,
PyObject* (*converter)(const TR x)) {
2013-12-05 17:11:01 +00:00
return list_output_helper(vec, converter);
}
template <class T>
2020-10-29 14:25:39 +01:00
inline PyObject* vector_output_helper(const std::vector<T*>* vec,
const OutConverter<T*>& converter) {
2013-12-05 17:11:01 +00:00
return list_output_helper(vec, converter);
}
template <class T>
2020-10-29 14:25:39 +01:00
inline PyObject* vector_output_wrap_helper(const std::vector<T*>* vec,
swig_type_info* swig_Tp_type,
2013-12-05 17:11:01 +00:00
bool newobj = false) {
#if 1
2020-10-29 14:25:39 +01:00
OutConverter<T*> converter(swig_Tp_type, newobj);
2013-12-05 17:11:01 +00:00
return vector_output_helper(vec, converter);
2020-10-22 23:36:58 +02:00
#else // Lambda version
2020-10-29 14:25:39 +01:00
auto converter = [](const T* x) {
return SWIG_NewPointerObj((void*)x, swig_Tp_type, newobj); // NOLINT
2020-10-22 23:36:58 +02:00
} return list_output_helper(vec, converter);
2013-12-05 17:11:01 +00:00
#endif
}
#if PY_MAJOR_VERSION > 2
/* SWIG 2's own C preprocessor macro for this is too strict.
* It requires a (x) parameter which doesn't work for the case where the
* function is being passed by & as a converter into a helper such as
* vector_output_helper above. */
#undef PyInt_FromLong
#define PyInt_FromLong PyLong_FromLong
#endif
2014-07-09 09:58:03 +00:00
2020-10-22 23:36:58 +02:00
#endif // OR_TOOLS_BASE_PYTHON_SWIG_H_