chiark / gitweb /
first stab at SWIG wrappers (unfinished Makefile), starting with Guile
authorstevenj <stevenj@alum.mit.edu>
Wed, 2 Jun 2010 06:22:44 +0000 (02:22 -0400)
committerstevenj <stevenj@alum.mit.edu>
Wed, 2 Jun 2010 06:22:44 +0000 (02:22 -0400)
darcs-hash:20100602062244-c8de0-d776ad5f27c68cc6b6d5799d341d4bb0b0264c58.gz

swig/Makefile.am [new file with mode: 0644]
swig/nlopt-guile.i [new file with mode: 0644]
swig/nlopt.i [new file with mode: 0644]

diff --git a/swig/Makefile.am b/swig/Makefile.am
new file mode 100644 (file)
index 0000000..b362fa7
--- /dev/null
@@ -0,0 +1,15 @@
+EXTRA_DIST = nlopt.i nlopt-guile.i
+
+BUILT_SOURCES = nlopt-guile.cpp nlopt-renames.i
+
+HDR = $(top_srcdir)/api/nlopt.hpp
+
+if MAINTAINER_MODE
+
+nlopt-guile.cpp: nlopt.i nlopt-enum-renames.i nlopt-guile.i $(top_builddir)/api/nlopt.hpp
+       swig -I$(top_builddir)/api -outdir $(builddir) -c++ -guile -scmstub -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) > $@
+
+endif
diff --git a/swig/nlopt-guile.i b/swig/nlopt-guile.i
new file mode 100644 (file)
index 0000000..7414b8a
--- /dev/null
@@ -0,0 +1,41 @@
+// -*- C++ -*-
+
+%{
+static double vfunc_guile(const std::vector<double> &x,
+                          std::vector<double> &grad, void *f) {
+  SCM xscm = scm_c_make_vector(x.size(), SCM_UNSPECIFIED);
+  for (unsigned i = 0; i < x.size(); ++i)
+    scm_c_vector_set_x(xscm, i, scm_make_real(x[i]));
+  SCM ret = scm_call_2((SCM) f, xscm);
+  if (scm_real_p(ret)) {
+    if (grad.size()) throw std::invalid_argument("missing gradient");
+    return scm_to_double(ret);
+  }
+  else if (scm_is_pair(ret)) { /* must be (cons value gradient) */
+    SCM valscm = SCM_CAR(ret), grad_scm = grad_scm;
+    if (grad.size() > 0
+       && scm_is_vector(grad_scm)
+       && scm_c_vector_length(grad_scm) == grad.size()) {
+      for (unsigned i = 0; i < grad.size(); ++i)
+       grad[i] = scm_to_double(scm_c_vector_ref(grad_scm, i));
+    }
+    else throw std::invalid_argument("invalid gradient");
+    if (scm_real_p(valscm))
+      return scm_to_double(valscm);
+  }
+  throw std::invalid_argument("invalid result passed to nlopt");
+}
+%}
+
+%typemap(in)(nlopt::vfunc vf, void *f_data) {
+  $1 = vfunc_guile;
+  $2 = (void*) $input; // input is SCM pointer to Scheme function
+}
+
+// export constants as variables, rather than as functions returning the value
+%feature("constasvar", "1");
+
+%scheme %{ 
+(dynamic-link "libnlopt.so")
+(load-extension "libnlopt-guile.so" "SWIG_init")
+%}
diff --git a/swig/nlopt.i b/swig/nlopt.i
new file mode 100644 (file)
index 0000000..01dc679
--- /dev/null
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+%module nlopt
+%{
+#include "nlopt.hpp"
+%}
+
+%include "std_vector.i"
+namespace std {
+  %template(nlopt_doublevector) vector<double>;
+};
+
+%rename(nlopt_opt) nlopt::opt;
+%rename(nlopt_roundoff_limited) nlopt::roundoff_limited;
+%rename(nlopt_forced_stop) nlopt::forced_stop;
+%rename(nlopt_srand) nlopt::srand;
+%rename(nlopt_srand_time) nlopt::srand_time;
+%rename(nlopt_version) nlopt::version;
+%rename(nlopt_algorithm_name) nlopt::algorithm_name;
+%include "nlopt-enum-renames.i"
+
+#ifdef SWIGGUILE
+%include "nlopt-guile.i"
+#endif
+
+%include "nlopt.hpp"