Files
ortools-clone/ortools/util/python/functions.i

227 lines
6.4 KiB
OpenEdge ABL
Raw Normal View History

// Copyright 2010-2021 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.
// This file provides swig wrapping for some specialization of std::function
// parameters. Currently, swig does not support much of C++11 features, and
// especially not the std::function.
//
// For now, clients must %include this.
// TODO(user): move the C++ code to a separate file, so that clients can
// simply %import this (and %{ #include %} the C++ file).
//
// Usage and tests in pywrapfunctions_test.py
%include "ortools/base/base.i"
%{
#include <functional>
2017-07-07 11:13:20 -07:00
// A copyable, ref-counted python pointer.
// TODO(user): Make it movable-only when we support generalized lambda
// capture.
class SharedPyPtr {
public:
explicit SharedPyPtr(PyObject* obj) : obj_(obj) { Py_INCREF(obj_); }
SharedPyPtr(const SharedPyPtr& other) : obj_(other.obj_) { Py_INCREF(obj_); }
~SharedPyPtr() { Py_DECREF(obj_); }
PyObject* get() const { return obj_; }
private:
// We do not follow the rule of three as we only want to copy construct.
SharedPyPtr& operator=(const SharedPyPtr&);
2017-07-07 11:13:20 -07:00
PyObject* const obj_;
};
template <typename ReturnT>
static ReturnT HandleResult(PyObject* pyresult) {
2019-09-03 15:43:48 +02:00
// This zero-initializes builtin types.
2017-07-07 11:13:20 -07:00
ReturnT result = ReturnT();
if (!pyresult) {
2019-09-03 15:43:48 +02:00
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError,
"SWIG std::function invocation failed.");
}
2017-07-07 11:13:20 -07:00
return result;
} else {
2017-07-07 11:13:20 -07:00
if (!PyObjAs<ReturnT>(pyresult, &result)) {
2019-09-03 15:43:48 +02:00
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError,
"SWIG std::function invocation failed.");
}
2017-07-07 11:13:20 -07:00
}
Py_DECREF(pyresult);
}
return result;
}
2017-07-07 11:13:20 -07:00
template <>
2019-09-03 15:43:48 +02:00
void HandleResult<void>(PyObject * pyresult) {
2017-07-07 11:13:20 -07:00
if (!pyresult) {
2019-09-03 15:43:48 +02:00
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError,
"SWIG std::function invocation failed.");
}
2017-07-07 11:13:20 -07:00
} else {
Py_DECREF(pyresult);
}
}
template <typename ReturnT, typename... Args>
static ReturnT InvokePythonCallableReturning(PyObject* pyfunc,
const char* format, Args... args) {
// The const_cast is safe (it's here only because the python API is not
// const-correct).
return HandleResult<ReturnT>(
PyObject_CallFunction(pyfunc, const_cast<char*>(format), args...));
}
template <typename ReturnT>
static ReturnT InvokePythonCallableReturning(PyObject* pyfunc) {
return HandleResult<ReturnT>(PyObject_CallFunctionObjArgs(pyfunc, nullptr));
}
%}
2017-07-07 11:13:20 -07:00
// Wrap std::function<std::string()>
%typecheck(SWIG_TYPECHECK_POINTER) std::function<std::string()> {
$1 = PyCallable_Check($input);
}
%typemap(in) std::function<std::string()> {
2017-07-07 11:13:20 -07:00
SharedPyPtr input($input);
$1 = [input]() { return InvokePythonCallableReturning<std::string>(input.get()); };
}
2021-04-01 12:13:35 +02:00
// Wrap std::function<int64_t(int64_t)>
2021-04-01 12:13:35 +02:00
%typecheck(SWIG_TYPECHECK_POINTER) std::function<int64_t(int64_t)> {
$1 = PyCallable_Check($input);
}
2021-04-01 12:13:35 +02:00
%typemap(in) std::function<int64_t(int64_t)> {
2017-07-07 11:13:20 -07:00
SharedPyPtr input($input);
2021-04-01 12:13:35 +02:00
$1 = [input](int64_t index) {
return InvokePythonCallableReturning<int64_t>(input.get(), "(L)", index);
2017-07-07 11:13:20 -07:00
};
}
2021-04-01 12:13:35 +02:00
// Wrap std::function<int64_t(int64_t, int64_t)>
2021-04-01 12:13:35 +02:00
%typecheck(SWIG_TYPECHECK_POINTER) std::function<int64_t(int64_t, int64_t)> {
$1 = PyCallable_Check($input);
}
2021-04-01 12:13:35 +02:00
%typemap(in) std::function<int64_t(int64_t, int64_t)> {
2017-07-07 11:13:20 -07:00
SharedPyPtr input($input);
2021-04-01 12:13:35 +02:00
$1 = [input](int64_t i, int64_t j) {
return InvokePythonCallableReturning<int64_t>(input.get(), "LL", i, j);
};
}
2021-04-01 12:13:35 +02:00
// Wrap std::function<int64_t(int64_t, int64_t, int64_t)>
2021-04-01 12:13:35 +02:00
%typecheck(SWIG_TYPECHECK_POINTER) std::function<int64_t(int64_t, int64_t, int64_t)> {
$1 = PyCallable_Check($input);
}
2021-04-01 12:13:35 +02:00
%typemap(in) std::function<int64_t(int64_t, int64_t, int64_t)> {
2017-07-07 11:13:20 -07:00
SharedPyPtr input($input);
2021-04-01 12:13:35 +02:00
$1 = [input](int64_t i, int64_t j, int64_t k) {
return InvokePythonCallableReturning<int64_t>(input.get(), "LLL", i, j, k);
};
}
2021-04-01 12:13:35 +02:00
// Wrap std::function<int64_t(int)>
2021-04-01 12:13:35 +02:00
%typecheck(SWIG_TYPECHECK_POINTER) std::function<int64_t(int)> {
$1 = PyCallable_Check($input);
}
2021-04-01 12:13:35 +02:00
%typemap(in) std::function<int64_t(int)> {
2017-07-07 11:13:20 -07:00
SharedPyPtr input($input);
$1 = [input](int index) {
2021-04-01 12:13:35 +02:00
return InvokePythonCallableReturning<int64_t>(input.get(), "(i)", index);
2017-07-07 11:13:20 -07:00
};
}
2021-04-01 12:13:35 +02:00
// Wrap std::function<int64_t(int, int)>
2021-04-01 12:13:35 +02:00
%typecheck(SWIG_TYPECHECK_POINTER) std::function<int64_t(int, int)> {
$1 = PyCallable_Check($input);
}
2021-04-01 12:13:35 +02:00
%typemap(in) std::function<int64_t(int, int)> {
2017-07-07 11:13:20 -07:00
SharedPyPtr input($input);
$1 = [input](int i, int j) {
2021-04-01 12:13:35 +02:00
return InvokePythonCallableReturning<int64_t>(input.get(), "ii", i, j);
};
}
2021-04-01 12:13:35 +02:00
// Wrap std::function<bool(int64_t)>
2021-04-01 12:13:35 +02:00
%typecheck(SWIG_TYPECHECK_POINTER) std::function<bool(int64_t)> {
$1 = PyCallable_Check($input);
}
2021-04-01 12:13:35 +02:00
%typemap(in) std::function<bool(int64_t)> {
2017-07-07 11:13:20 -07:00
SharedPyPtr input($input);
2021-04-01 12:13:35 +02:00
$1 = [input](int64_t index) {
2019-02-18 15:27:32 +01:00
return InvokePythonCallableReturning<bool>(input.get(), "(L)", index);
2017-07-07 11:13:20 -07:00
};
}
// Wrap std::function<bool()>
%typecheck(SWIG_TYPECHECK_POINTER) std::function<bool()> {
$1 = PyCallable_Check($input);
}
%typemap(in) std::function<bool()> {
2017-07-07 11:13:20 -07:00
SharedPyPtr input($input);
$1 = [input]() { return InvokePythonCallableReturning<bool>(input.get()); };
}
2017-07-07 11:13:20 -07:00
// Wrap std::function<void()>
%typecheck(SWIG_TYPECHECK_POINTER) std::function<void()> {
$1 = PyCallable_Check($input);
}
%typemap(in) std::function<void()> {
2017-07-07 11:13:20 -07:00
SharedPyPtr input($input);
$1 = [input]() { return InvokePythonCallableReturning<void>(input.get()); };
}
// Wrap std::function<void(std::string)>
%typecheck(SWIG_TYPECHECK_POINTER) std::function<void(const std::string&)> {
$1 = PyCallable_Check($input);
}
%typemap(in) std::function<void(const std::string&)> {
SharedPyPtr input($input);
$1 = [input](const std::string& str) {
PyObject* py_str = PyUnicode_FromStringAndSize(str.c_str(), str.size());
PyObject* result;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
2021-03-12 13:34:41 +01:00
result = PyObject_CallFunction(input.get(), "O", py_str);
SWIG_PYTHON_THREAD_END_BLOCK;
Py_DECREF(py_str);
return result;
};
}