SWIG_SRC = nlopt.i nlopt-exceptions.i nlopt-enum-renames.i
-EXTRA_DIST = $(SWIG_SRC) nlopt-guile.i nlopt.scm.in
+EXTRA_DIST = $(SWIG_SRC) nlopt-guile.i nlopt-python.i nlopt.scm.in
BUILT_SOURCES = nlopt-guile.cpp nlopt-enum-renames.i nlopt.scm.in
if MAINTAINER_MODE
-nlopt-guile.cpp: $(SWIG_SRC) nlopt-guile.i $(HDR)
+nlopt-guile.cpp nlopt.scm.in: $(SWIG_SRC) nlopt-guile.i $(HDR)
swig -I$(top_builddir)/api -outdir $(builddir) -c++ -guile -scmstub -o $@ nlopt.i
rm -f nlopt.scm.in
mv nlopt.scm nlopt.scm.in
+nlopt-python.cpp nlopt.py: $(SWIG_SRC) nlopt-python.i $(HDR)
+ swig -I$(top_builddir)/api -outdir $(builddir) -c++ -python -o $@ nlopt.i
+
nlopt-enum-renames.i: $(top_srcdir)/api/nlopt.h
(echo "// AUTOMATICALLY GENERATED -- DO NOT EDIT"; egrep 'NLOPT_[LG][DN]|NLOPT_NUM_ALGORITHMS' $(top_srcdir)/api/nlopt.h | sed 's/NLOPT_//g' |tr -d ' ' |tr '/' ',' |tr '=' ',' |cut -d, -f1 |while read name; do echo "%rename(NLOPT_$$name) nlopt::$$name;"; done; egrep 'NLOPT_[A-Z_]* =' $(top_srcdir)/api/nlopt.h | egrep -v 'NLOPT_[LG][DN]' | sed 's/NLOPT_//g' |tr -d ' ' |cut -d'=' -f1 | while read name; do echo "%rename(NLOPT_$$name) nlopt::$$name;"; done) > $@
--- /dev/null
+// -*- C++ -*-
+
+//////////////////////////////////////////////////////////////////////////////
+
+%{
+#define SWIG_FILE_WITH_INIT
+#define array_stride(a,i) (((PyArrayObject *)a)->strides[i])
+%}
+%include "numpy.i"
+%init %{
+ import_array();
+%}
+%numpy_typemaps(double, NPY_DOUBLE, unsigned)
+
+//////////////////////////////////////////////////////////////////////////////
+// numpy.i does not include maps for std::vector<double>, so I add them here,
+// taking advantage of the conversion functions provided by numpy.i
+
+// Typemap for input arguments of type const std::vector<double> &
+%typecheck(SWIG_TYPECHECK_POINTER, fragment="NumPy_Macros")
+ const std::vector<double> &
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in, fragment="NumPy_Fragments")
+ const std::vector<double> &
+(PyArrayObject* array=NULL, int is_new_object=0, std::vector<double> arrayv)
+{
+ npy_intp size[1] = { -1 };
+ array = obj_to_array_allow_conversion($input, DATA_TYPECODE, &is_new_object);
+ if (!array || !require_dimensions(array, 1) ||
+ !require_size(array, size, 1)) SWIG_fail;
+ arrayv = std::vector<double>(array_size(array,0));
+ $1 = &arrayv;
+ {
+ double *arr_data = (double *) array_data(array);
+ int arr_i, arr_s = array_stride(array,0), arr_sz = array_size(array,0);
+ for (arr_i = 0; arr_i < arr_sz; ++arr_i)
+ arrayv[arr_i] = arr_data[arr_i * arr_s];
+ }
+}
+%typemap(freearg)
+ const std::vector<double> &
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+// Typemap for return values of type std::vector<double>
+%typemap(out, fragment="NumPy_Fragments") std::vector<double>
+{
+ npy_intp sz = $1.size();
+ $result = PyArray_SimpleNew(1, &sz, NPY_DOUBLE);
+ std::memcpy(array_data($result), $1.empty() ? NULL : &$1[0],
+ sizeof(double) * sz);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Wrapper for objective function callbacks
+
+%{
+static double func_python(unsigned n, const double *x, double *grad, void *f)
+{
+ npy_intp sz = npy_intp(n), sz0 = 0;
+ PyObject *xpy = PyArray_SimpleNewFromData(1, &sz, NPY_DOUBLE, x);
+ PyObject *gradpy = grad ? PyArray_SimpleNew(1, &sz0, NPY_DOUBLE)
+ : PyArray_SimpleNewFromData(1, &sz, NPY_DOUBLE, grad);
+
+ PyObject *arglist = Py_BuildValue("OO", xpy, gradpy);
+ PyObject *result = PyEval_CallObject((PyObject *) f, arglist);
+ Py_DECREF(arglist);
+
+ Py_DECREF(gradpy);
+ Py_DECREF(xpy);
+
+ double val = HUGE_VAL;
+ if (SWIG_IsOK(SWIG_AsVal_double(result, &val))) {
+ Py_DECREF(result);
+ }
+ else {
+ Py_DECREF(result);
+ throw std::invalid_argument("invalid result passed to nlopt");
+ }
+ return val;
+}
+%}
+
+%typemap(in)(nlopt::func f, void *f_data) {
+ Py_INCREF($input);
+ $1 = func_python;
+ $2 = (void*) $input;
+}
+%typecheck(SWIG_TYPECHECK_POINTER)(nlopt::func f, void *f_data) {
+ $1 = PyCallable_Check($input);
+}