forked from google/or-tools
-
Notifications
You must be signed in to change notification settings - Fork 2
/
python-swig.h
364 lines (330 loc) · 10.3 KB
/
python-swig.h
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
// Copyright 2010-2024 Google LLC
// 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.
// 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:
// #ifdef SWIGPYTHON
// %{
// #include "ortools/base/swig/python-swig.cc"
// %}
// #endif
// It has no XXX_H_ guard because SWIG protects all %include'd files to be used
// only once.
#ifndef OR_TOOLS_BASE_PYTHON_SWIG_H_
#define OR_TOOLS_BASE_PYTHON_SWIG_H_
#if PY_VERSION_HEX >= 0x03030000 // Py3.3+
// 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
static inline int PyString_AsStringAndSize(PyObject* obj, char** buf,
Py_ssize_t* psize) {
if (PyUnicode_Check(obj)) {
*buf = const_cast<char*>(PyUnicode_AsUTF8AndSize(obj, psize));
return *buf == nullptr ? -1 : 0;
} else if (PyBytes_Check(obj)) {
return PyBytes_AsStringAndSize(obj, buf, psize);
}
PyErr_SetString(PyExc_TypeError, "Expecting str or bytes");
return -1;
}
#endif // Py3.3+
template <class T>
inline bool PyObjAs(PyObject* pystr, T* cstr) {
T::undefined; // You need to define specialization PyObjAs<T>
}
template <class T>
inline PyObject* PyObjFrom(const T& c) {
T::undefined; // You need to define specialization PyObjFrom<T>
}
#ifdef HAS_GLOBAL_STRING
template <>
inline bool PyObjAs(PyObject* pystr, ::std::string* cstr) {
char* buf;
Py_ssize_t len;
#if PY_VERSION_HEX >= 0x03030000
if (PyUnicode_Check(pystr)) {
buf = PyUnicode_AsUTF8AndSize(pystr, &len);
if (!buf) return false;
} else // NOLINT
#endif
if (PyBytes_AsStringAndSize(pystr, &buf, &len) == -1)
return false;
if (cstr) cstr->assign(buf, len);
return true;
}
#endif
template <class T>
inline bool PyObjAs(PyObject* pystr, std::string* cstr) {
char* buf;
Py_ssize_t len;
#if PY_VERSION_HEX >= 0x03030000
if (PyUnicode_Check(pystr)) {
buf = const_cast<char*>(PyUnicode_AsUTF8AndSize(pystr, &len));
if (!buf) return false;
} else // NOLINT
#endif
if (PyBytes_AsStringAndSize(pystr, &buf, &len) == -1)
return false;
if (cstr) cstr->assign(buf, len);
return true;
}
#ifdef HAS_GLOBAL_STRING
template <>
inline PyObject* PyObjFrom(const ::std::string& c) {
return PyString_FromStringAndSize(c.data(), c.size());
}
#endif
template <>
inline PyObject* PyObjFrom(const std::string& c) {
return PyString_FromStringAndSize(c.data(), c.size());
}
// Do numeric specialization.
#include <limits>
template <>
inline bool PyObjAs(PyObject* py, int* c) {
long i = PyInt_AsLong(py); // NOLINT
if (i == -1 && PyErr_Occurred()) // TypeError or OverflowError.
return false; // Not a Python int.
if (i < std::numeric_limits<int>::min() ||
i > std::numeric_limits<int>::max())
return false; // Not C int.
if (c) *c = static_cast<int>(i);
return true;
}
template <>
inline bool PyObjAs(PyObject* py, unsigned int* c) {
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);
return true;
}
template <>
inline bool PyObjAs(PyObject* py, int64_t* c) { // NOLINT
int64_t i; // NOLINT
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(py)) {
i = PyInt_AsLong(py);
} else {
if (!PyLong_Check(py)) return false; // Not a Python long.
#else
{
#endif
i = PyLong_AsLongLong(py);
if (i == -1 && PyErr_Occurred()) return false; // Not a C long long.
}
if (c) *c = i;
return true;
}
template <>
inline bool PyObjAs(PyObject* py, uint64_t* c) { // NOLINT
uint64_t i; // NOLINT
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(py)) {
i = PyInt_AsUnsignedLongLongMask(py);
} else // NOLINT
#endif
{
if (!PyLong_Check(py)) return false; // Not a Python long.
i = PyLong_AsUnsignedLongLong(py);
if (i == (uint64_t)-1 && PyErr_Occurred()) // NOLINT
return false;
}
if (c) *c = i;
return true;
}
template <>
inline bool PyObjAs(PyObject* py, double* c) {
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)) {
return false; // float or int/long expected
#endif
} else {
d = PyLong_AsDouble(py);
if (d == -1.0 && PyErr_Occurred()) {
return false; // Overflow (or TypeError for PY3)
}
}
if (c) *c = d;
return true;
}
template <>
inline PyObject* PyObjFrom(const double& c) {
return PyFloat_FromDouble(c);
}
template <>
inline bool PyObjAs(PyObject* py, float* c) {
double d;
if (!PyObjAs(py, &d)) return false;
if (c) *c = static_cast<float>(d);
return true;
}
template <>
inline PyObject* PyObjFrom(const float& c) {
return PyFloat_FromDouble(c);
}
template <>
inline bool PyObjAs(PyObject* py, bool* c) {
if (!PyBool_Check(py)) return false; // Not a Python bool.
if (c) *c = PyObject_Not(py) ? false : true;
return true;
}
inline int SwigPyIntOrLong_Check(PyObject* o) {
return (PyLong_Check(o)
#if PY_MAJOR_VERSION <= 2
|| PyInt_Check(o)
#endif
); // NOLINT
}
inline int SwigString_Check(PyObject* o) { return PyUnicode_Check(o); }
inline PyObject* SwigString_FromString(const std::string& s) {
return PyString_FromStringAndSize(s.data(), s.size());
}
inline std::string SwigString_AsString(PyObject* o) {
return std::string(PyString_AsString(o));
}
// STL std::vector<T> for common types
namespace { // NOLINT
template <typename T>
struct vector_pusher {
typedef T* ptr;
static void push(std::vector<T>* o, ptr e) { o->push_back(*e); }
};
template <typename T>
struct vector_pusher<T*> {
typedef T* ptr;
static void push(std::vector<T*>* o, ptr e) { o->push_back(e); }
};
}; // namespace
template <class T>
inline bool vector_input_helper(PyObject* seq, std::vector<T>* out,
bool (*convert)(PyObject*, T* const)) {
PyObject *item, *it = PyObject_GetIter(seq);
if (!it) return false;
T elem;
while ((item = PyIter_Next(it))) {
bool success = convert(item, &elem);
Py_DECREF(item);
if (!success) {
Py_DECREF(it);
return false;
}
if (out) out->push_back(elem);
}
Py_DECREF(it);
return static_cast<bool>(!PyErr_Occurred());
}
template <class T>
inline bool vector_input_wrap_helper(PyObject* seq, std::vector<T>* out,
swig_type_info* swig_Tp_type) {
PyObject *item, *it = PyObject_GetIter(seq);
if (!it) {
PyErr_SetString(PyExc_TypeError, "sequence expected");
return false;
}
typename vector_pusher<T>::ptr elem;
while ((item = PyIter_Next(it))) {
if (SWIG_ConvertPtr(item, reinterpret_cast<void**>(&elem), swig_Tp_type,
0) == -1) {
Py_DECREF(it);
it = PyObject_Repr(item);
Py_DECREF(item);
const char* repr = it ? PyString_AsString(it) : "not";
PyErr_Format(PyExc_TypeError, "'%s' expected, %s found",
SWIG_TypePrettyName(swig_Tp_type), repr);
Py_XDECREF(it);
return false;
}
Py_DECREF(item);
if (out) vector_pusher<T>::push(out, elem);
}
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>
inline PyObject* list_output_helper(const T* vec, Converter converter) {
if (vec == nullptr) Py_RETURN_NONE; // Return a nice out-of-band value.
PyObject* lst = PyList_New(vec->size());
if (lst == nullptr) return nullptr;
int i = 0;
for (typename T::const_reference pt : *vec) {
PyObject* obj = converter(pt);
if (!obj) {
Py_DECREF(lst);
return nullptr;
}
PyList_SET_ITEM(lst, i++, obj);
}
return lst;
}
template <class T>
struct OutConverter {
PyObject* operator()(const T x) const {
return SWIG_NewPointerObj((void*)x, type_, new_); // NOLINT
}
swig_type_info* type_;
int new_;
OutConverter(swig_type_info* type, int new_object)
: type_(type), new_(new_object) {}
};
template <class T, class TR>
inline PyObject* vector_output_helper(const std::vector<T>* vec,
PyObject* (*converter)(const TR x)) {
return list_output_helper(vec, converter);
}
template <class T>
inline PyObject* vector_output_helper(const std::vector<T*>* vec,
const OutConverter<T*>& converter) {
return list_output_helper(vec, converter);
}
template <class T>
inline PyObject* vector_output_wrap_helper(const std::vector<T*>* vec,
swig_type_info* swig_Tp_type,
bool newobj = false) {
#if 1
OutConverter<T*> converter(swig_Tp_type, newobj);
return vector_output_helper(vec, converter);
#else // Lambda version
auto converter = [](const T* x) {
return SWIG_NewPointerObj((void*)x, swig_Tp_type, newobj); // NOLINT
} return list_output_helper(vec, converter);
#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
#endif // OR_TOOLS_BASE_PYTHON_SWIG_H_