From c939fbd74eb5b32f94f6a3971c4975981e58fa45 Mon Sep 17 00:00:00 2001 From: stevenj Date: Thu, 3 Jun 2010 22:03:46 -0400 Subject: [PATCH] support exceptions in SWIG wrappers darcs-hash:20100604020346-c8de0-b94b0853daeba61580499c4385089737b6d9d221.gz --- api/nlopt-in.hpp | 41 +++++++++++++++++----------- api/options.c | 2 ++ swig/Makefile.am | 5 ++-- swig/nlopt-exceptions.i | 59 +++++++++++++++++++++++++++++++++++++++++ swig/nlopt.i | 2 ++ 5 files changed, 92 insertions(+), 17 deletions(-) create mode 100644 swig/nlopt-exceptions.i diff --git a/api/nlopt-in.hpp b/api/nlopt-in.hpp index 08f89f1..a44cd8c 100644 --- a/api/nlopt-in.hpp +++ b/api/nlopt-in.hpp @@ -223,7 +223,7 @@ namespace nlopt { // Nonlinear constraints: - void remove_inequality_constraints(void) { + void remove_inequality_constraints() { nlopt_result ret = nlopt_remove_inequality_constraints(o); mythrow(ret); } @@ -241,7 +241,7 @@ namespace nlopt { alloc_tmp(); } - void remove_equality_constraints(void) { + void remove_equality_constraints() { nlopt_result ret = nlopt_remove_equality_constraints(o); mythrow(ret); } @@ -261,16 +261,14 @@ namespace nlopt { #define NLOPT_GETSET_VEC(name) \ void set_##name(double val) { \ - nlopt_result ret = nlopt_set_##name##1(o, val); \ - mythrow(ret); \ + mythrow(nlopt_set_##name##1(o, val)); \ } \ void get_##name(std::vector &v) const { \ if (o && nlopt_get_dimension(o) != v.size()) \ throw std::invalid_argument("dimension mismatch"); \ - nlopt_result ret = nlopt_get_##name(o, v.empty() ? NULL : &v[0]); \ - mythrow(ret); \ + mythrow(nlopt_get_##name(o, v.empty() ? NULL : &v[0])); \ } \ - std::vector get_##name(void) const { \ + std::vector get_##name() const { \ if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \ std::vector v(nlopt_get_dimension(o)); \ get_##name(v); \ @@ -279,8 +277,7 @@ namespace nlopt { void set_##name(const std::vector &v) { \ if (o && nlopt_get_dimension(o) != v.size()) \ throw std::invalid_argument("dimension mismatch"); \ - nlopt_result ret = nlopt_set_##name(o, v.empty() ? NULL : &v[0]); \ - mythrow(ret); \ + mythrow(nlopt_set_##name(o, v.empty() ? NULL : &v[0])); \ } NLOPT_GETSET_VEC(lower_bounds) @@ -294,8 +291,7 @@ namespace nlopt { return nlopt_get_##name(o); \ } \ void set_##name(T name) { \ - nlopt_result ret = nlopt_set_##name(o, name); \ - mythrow(ret); \ + mythrow(nlopt_set_##name(o, name)); \ } NLOPT_GETSET(double, stopval) NLOPT_GETSET(double, ftol_rel) @@ -344,12 +340,27 @@ namespace nlopt { ////////////////////////////////////////////////////////////////////// - inline void srand(unsigned long seed) { nlopt_srand(seed); } - inline void srand_time(void) { nlopt_srand_time(); } - inline void version(int &major, int &minor, int &bugfix) { + void srand(unsigned long seed) { nlopt_srand(seed); } + void srand_time() { nlopt_srand_time(); } + void version(int &major, int &minor, int &bugfix) { nlopt_version(&major, &minor, &bugfix); } - inline const char *algorithm_name(algorithm a) { + int version_major() { + int major, minor, bugfix; + nlopt_version(&major, &minor, &bugfix); + return major; + } + int version_minor() { + int major, minor, bugfix; + nlopt_version(&major, &minor, &bugfix); + return minor; + } + int version_bugfix() { + int major, minor, bugfix; + nlopt_version(&major, &minor, &bugfix); + return bugfix; + } + const char *algorithm_name(algorithm a) { return nlopt_algorithm_name(nlopt_algorithm(a)); } diff --git a/api/options.c b/api/options.c index 614ec00..e766ca4 100644 --- a/api/options.c +++ b/api/options.c @@ -261,6 +261,7 @@ nlopt_result nlopt_get_upper_bounds(nlopt_opt opt, double *ub) nlopt_result nlopt_remove_inequality_constraints(nlopt_opt opt) { + if (!opt) return NLOPT_INVALID_ARGS; free(opt->fc); opt->fc = NULL; opt->m = opt->m_alloc = 0; @@ -313,6 +314,7 @@ nlopt_result nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_result nlopt_remove_equality_constraints(nlopt_opt opt) { + if (!opt) return NLOPT_INVALID_ARGS; free(opt->h); opt->h = NULL; opt->p = opt->p_alloc = 0; diff --git a/swig/Makefile.am b/swig/Makefile.am index 4766ade..3700643 100644 --- a/swig/Makefile.am +++ b/swig/Makefile.am @@ -1,4 +1,5 @@ -EXTRA_DIST = nlopt.i nlopt-guile.i nlopt-enum-renames.i nlopt.scm.in +SWIG_SRC = nlopt.i nlopt-exceptions.i nlopt-enum-renames.i +EXTRA_DIST = $(SWIG_SRC) nlopt-guile.i nlopt.scm.in BUILT_SOURCES = nlopt-guile.cpp nlopt-enum-renames.i nlopt.scm.in @@ -29,7 +30,7 @@ lib_LTLIBRARIES = $(guilelib) if MAINTAINER_MODE -nlopt-guile.cpp: nlopt.i nlopt-enum-renames.i nlopt-guile.i $(HDR) +nlopt-guile.cpp: $(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 diff --git a/swig/nlopt-exceptions.i b/swig/nlopt-exceptions.i new file mode 100644 index 0000000..e7693da --- /dev/null +++ b/swig/nlopt-exceptions.i @@ -0,0 +1,59 @@ +// since exception specifications in C++ are evil, we instead provide +// %catches specifications here so that SWIG can generate language-specific +// exceptions (at least for exceptions explicitly thrown by NLopt) +// +// manually doing this stuff is annoying + +%catches(std::bad_alloc) nlopt::opt::opt(); +%catches(std::bad_alloc) nlopt::opt::opt(algorithm a, unsigned n); +%catches(std::bad_alloc) nlopt::opt::opt(const opt& f); +%catches(std::bad_alloc) nlopt::opt::operator=(opt const& f); + +%catches(nlopt::roundoff_limited,nlopt::forced_stop,std::runtime_error,std::bad_alloc,std::invalid_argument) nlopt::opt::optimize(std::vector &x, double &opt_f); +%catches(nlopt::roundoff_limited,nlopt::forced_stop,std::runtime_error,std::bad_alloc,std::invalid_argument) nlopt::opt::optimize(const std::vector &x0); + +%catches(std::runtime_error) nlopt::opt::get_algorithm(); +%catches(std::runtime_error) nlopt::opt::get_algorithm_name(); +%catches(std::runtime_error) nlopt::opt::get_dimension(); + +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_min_objective(func f, void *f_data); +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_min_objective(vfunc vf, void *f_data); +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_max_objective(func f, void *f_data); +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_max_objective(vfunc vf, void *f_data); + +%catches(std::invalid_argument) nlopt::opt::remove_inequality_constraints(); +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_inequality_constraint(func f, void *f_data, double tol=0); +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_inequality_constraint(vfunc vf, void *f_data, double tol=0); +%catches(std::invalid_argument) nlopt::opt::remove_equality_constraints(); +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_equality_constraint(func f, void *f_data, double tol=0); +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::add_equality_constraint(vfunc vf, void *f_data, double tol=0); + +#define SET_EXCEPT(name, T) %catches(std::invalid_argument) nlopt::opt::set_##name(T val); +#define GET_EXCEPT(name) %catches(std::invalid_argument) nlopt::opt::get_##name(); +#define SETVEC_EXCEPT(name) %catches(std::invalid_argument) nlopt::opt::set_##name(const std::vector &v); +#define GETVEC_EXCEPT(name) %catches(std::bad_alloc,std::invalid_argument) nlopt::opt::get_##name(std::vector &v); +#define GETSET_EXCEPT(name, T) GET_EXCEPT(name) SET_EXCEPT(name, T) +#define GETSETVEC_EXCEPT(name) GET_EXCEPT(name) SET_EXCEPT(name, double) GETVEC_EXCEPT(name) SETVEC_EXCEPT(name) + +GETSETVEC_EXCEPT(lower_bounds) +GETSETVEC_EXCEPT(upper_bounds) + +GETSET_EXCEPT(stopval, double) +GETSET_EXCEPT(ftol_rel, double) +GETSET_EXCEPT(ftol_abs, double) +GETSET_EXCEPT(xtol_rel, double) +GETSETVEC_EXCEPT(xtol_abs) +GETSET_EXCEPT(maxeval, int) +GETSET_EXCEPT(maxtime, double) +GETSET_EXCEPT(force_stop, int) + +%catches(std::invalid_argument) nlopt::opt::force_stop(); + +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_local_optimizer(const opt &lo); + +GETSET_EXCEPT(local_population, unsigned) +GETSETVEC_EXCEPT(initial_step) + +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::set_default_initial_step(const std::vector &x); +%catches(std::invalid_argument) nlopt::opt::get_initial_step(const std::vector &x, std::vector &dx); +%catches(std::bad_alloc,std::invalid_argument) nlopt::opt::get_initial_step(const std::vector &x); diff --git a/swig/nlopt.i b/swig/nlopt.i index 01dc679..6f6f0b4 100644 --- a/swig/nlopt.i +++ b/swig/nlopt.i @@ -18,6 +18,8 @@ namespace std { %rename(nlopt_algorithm_name) nlopt::algorithm_name; %include "nlopt-enum-renames.i" +%include "nlopt-exceptions.i" + #ifdef SWIGGUILE %include "nlopt-guile.i" #endif -- 2.30.2