在 OR 工具中通过 SWIG 使用 Python 回调
Using Python callbacks via SWIG in OR Tools
我希望这是一个简单的 SWIG 问题。我正在使用 Google OR-Tools 优化库。它是一个包装在 SWIG 中的 C++ 库(我对此知之甚少)。我很难让 Python 回调函数工作。有一个C++函数
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
IndexEvaluator1* var_evaluator,
IntValueStrategy val_str);
连同
typedef ResultCallback1<int64, int64> IndexEvaluator1;
相关的 SWIG(我相信)是
DecisionBuilder* VarEvalValStrPhase(
const std::vector<IntVar*>& vars,
ResultCallback1<int64, int64>* var_evaluator,
operations_research::Solver::IntValueStrategy val_str) {
return self->MakePhase(vars, var_evaluator, val_str);
}
在另一个 SWIG 文件中我们有
%{
static int64 PyCallback1Int64Int64(PyObject* pyfunc, int64 i) {
// () needed to force creation of one-element tuple
PyObject* pyresult = PyEval_CallFunction(pyfunc, "(l)", static_cast<long>(i));
int64 result = 0;
if (!pyresult) {
PyErr_SetString(PyExc_RuntimeError,
"ResultCallback1<int64, int64> invocation failed.");
} else {
result = PyInt_AsLong(pyresult);
Py_DECREF(pyresult);
}
return result;
}
%}
%typemap(in) ResultCallback1<int64, int64>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
= NewPermanentCallback(&PyCallback1Int64Int64, $input);
}
在我的 Python 模块中,我定义了一个函数 Run1,如下所示(我认为这里应该有一些类型转换,但我认为这不是 Python方式):
def Run1(index1):
return index1
并设置
selector_callback = Run1
solver = pywrapcp.Solver("graph-coloring")
最后,我打电话给
solver.Phase(nodes,
selector_callback,
solver.INT_VALUE_DEFAULT)
唉,事情就这样卡布洛伊,我总是得到以下错误:
File "C:\dev\Python27\lib\site-packages\ortools-1.3853-py2.7-win-amd64.egg\ortools\constraint_solver\pywrapcp.py", line 457, in Phase
def Phase(self, *args): return _pywrapcp.Solver_Phase(self, *args)
NotImplementedError: Wrong number or type of arguments for overloaded function 'Solver_Phase'.
Possible C/C++ prototypes are:
operations_research::Solver::MakePhase(std::vector< operations_research::IntVar *,std::allocator< operations_research::IntVar * > > const &,operations_research::Solver::IntVarStrategy,operations_research::Solver::IntValueStrategy)
operations_research::Solver::MakePhase(std::vector< operations_research::IntervalVar *,std::allocator< operations_research::IntervalVar * > > const &,operations_research::Solver::IntervalStrategy)
operations_research::Solver::MakePhase(std::vector< operations_research::SequenceVar *,std::allocator< operations_research::SequenceVar * > > const &,operations_research::Solver::SequenceStrategy)
困难在于第二个参数中的回调函数;如果我使用内置值之一而不是回调,则操作成功。但是,我确实需要在那里有自己的功能。
我没有在我的模块中导入任何 SWIG 文件。我需要这样做吗?
几天后,我找到了答案。如果我打电话
solver.VarEvalValStrPhase(nodes,
selector_callback,
solver.INT_VALUE_DEFAULT)
而不是整个手册中引用的标准函数名称 Phase
,它可以工作。如果我要使用另一个参数组合,我相信我必须使用另一个函数名。在这种情况下,重载似乎失败了。这很好,但开发人员的警告会更好。
我希望这是一个简单的 SWIG 问题。我正在使用 Google OR-Tools 优化库。它是一个包装在 SWIG 中的 C++ 库(我对此知之甚少)。我很难让 Python 回调函数工作。有一个C++函数
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
IndexEvaluator1* var_evaluator,
IntValueStrategy val_str);
连同
typedef ResultCallback1<int64, int64> IndexEvaluator1;
相关的 SWIG(我相信)是
DecisionBuilder* VarEvalValStrPhase(
const std::vector<IntVar*>& vars,
ResultCallback1<int64, int64>* var_evaluator,
operations_research::Solver::IntValueStrategy val_str) {
return self->MakePhase(vars, var_evaluator, val_str);
}
在另一个 SWIG 文件中我们有
%{
static int64 PyCallback1Int64Int64(PyObject* pyfunc, int64 i) {
// () needed to force creation of one-element tuple
PyObject* pyresult = PyEval_CallFunction(pyfunc, "(l)", static_cast<long>(i));
int64 result = 0;
if (!pyresult) {
PyErr_SetString(PyExc_RuntimeError,
"ResultCallback1<int64, int64> invocation failed.");
} else {
result = PyInt_AsLong(pyresult);
Py_DECREF(pyresult);
}
return result;
}
%}
%typemap(in) ResultCallback1<int64, int64>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
= NewPermanentCallback(&PyCallback1Int64Int64, $input);
}
在我的 Python 模块中,我定义了一个函数 Run1,如下所示(我认为这里应该有一些类型转换,但我认为这不是 Python方式):
def Run1(index1):
return index1
并设置
selector_callback = Run1
solver = pywrapcp.Solver("graph-coloring")
最后,我打电话给
solver.Phase(nodes,
selector_callback,
solver.INT_VALUE_DEFAULT)
唉,事情就这样卡布洛伊,我总是得到以下错误:
File "C:\dev\Python27\lib\site-packages\ortools-1.3853-py2.7-win-amd64.egg\ortools\constraint_solver\pywrapcp.py", line 457, in Phase
def Phase(self, *args): return _pywrapcp.Solver_Phase(self, *args)
NotImplementedError: Wrong number or type of arguments for overloaded function 'Solver_Phase'.
Possible C/C++ prototypes are:
operations_research::Solver::MakePhase(std::vector< operations_research::IntVar *,std::allocator< operations_research::IntVar * > > const &,operations_research::Solver::IntVarStrategy,operations_research::Solver::IntValueStrategy)
operations_research::Solver::MakePhase(std::vector< operations_research::IntervalVar *,std::allocator< operations_research::IntervalVar * > > const &,operations_research::Solver::IntervalStrategy)
operations_research::Solver::MakePhase(std::vector< operations_research::SequenceVar *,std::allocator< operations_research::SequenceVar * > > const &,operations_research::Solver::SequenceStrategy)
困难在于第二个参数中的回调函数;如果我使用内置值之一而不是回调,则操作成功。但是,我确实需要在那里有自己的功能。
我没有在我的模块中导入任何 SWIG 文件。我需要这样做吗?
几天后,我找到了答案。如果我打电话
solver.VarEvalValStrPhase(nodes,
selector_callback,
solver.INT_VALUE_DEFAULT)
而不是整个手册中引用的标准函数名称 Phase
,它可以工作。如果我要使用另一个参数组合,我相信我必须使用另一个函数名。在这种情况下,重载似乎失败了。这很好,但开发人员的警告会更好。