@@ -17,6 +17,7 @@ namespace matplotlibcpp {
1717 namespace detail {
1818 struct _interpreter {
1919 PyObject *s_python_function_show;
20+ PyObject *s_python_function_save;
2021 PyObject *s_python_function_figure;
2122 PyObject *s_python_function_plot;
2223 PyObject *s_python_function_legend;
@@ -42,12 +43,17 @@ namespace matplotlibcpp {
4243 Py_SetProgramName (name); // optional but recommended
4344 Py_Initialize ();
4445
45- PyObject* pyname = PyString_FromString (" matplotlib.pyplot" );
46- if (!pyname) { throw std::runtime_error (" couldnt create string" ); }
46+ PyObject* pyplotname = PyString_FromString (" matplotlib.pyplot" );
47+ PyObject* pylabname = PyString_FromString (" pylab" );
48+ if (!pyplotname || !pylabname) { throw std::runtime_error (" couldnt create string" ); }
4749
48- PyObject* pymod = PyImport_Import (pyname);
49- Py_DECREF (pyname);
50- if (!pymod) { throw std::runtime_error (" Error loading module!" ); }
50+ PyObject* pymod = PyImport_Import (pyplotname);
51+ Py_DECREF (pyplotname);
52+ if (!pymod) { throw std::runtime_error (" Error loading module matplotlib.pyplot!" ); }
53+
54+ PyObject* pylabmod = PyImport_Import (pylabname);
55+ Py_DECREF (pylabname);
56+ if (!pymod) { throw std::runtime_error (" Error loading module pylab!" ); }
5157
5258 s_python_function_show = PyObject_GetAttrString (pymod, " show" );
5359 s_python_function_figure = PyObject_GetAttrString (pymod, " figure" );
@@ -56,7 +62,10 @@ namespace matplotlibcpp {
5662 s_python_function_ylim = PyObject_GetAttrString (pymod, " ylim" );
5763 s_python_function_xlim = PyObject_GetAttrString (pymod, " xlim" );
5864
65+ s_python_function_save = PyObject_GetAttrString (pylabmod, " savefig" );
66+
5967 if (!s_python_function_show
68+ || !s_python_function_save
6069 || !s_python_function_figure
6170 || !s_python_function_plot
6271 || !s_python_function_legend
@@ -65,6 +74,7 @@ namespace matplotlibcpp {
6574 { throw std::runtime_error (" Couldnt find required function!" ); }
6675
6776 if (!PyFunction_Check (s_python_function_show)
77+ || !PyFunction_Check (s_python_function_save)
6878 || !PyFunction_Check (s_python_function_figure)
6979 || !PyFunction_Check (s_python_function_plot)
7080 || !PyFunction_Check (s_python_function_legend)
@@ -127,8 +137,6 @@ namespace matplotlibcpp {
127137 {
128138 assert (x.size () == y.size ());
129139
130- // std::string format(s);
131-
132140 PyObject* xlist = PyList_New (x.size ());
133141 PyObject* ylist = PyList_New (y.size ());
134142 PyObject* pystring = PyString_FromString (s.c_str ());
@@ -192,25 +200,6 @@ namespace matplotlibcpp {
192200 return plot (x,y,format);
193201 }
194202
195- /*
196- * This group of plot() functions is needed to support initializer lists, i.e. calling
197- * plot( {1,2,3,4} )
198- */
199- bool plot (const std::vector<double >& x, const std::vector<double >& y, const std::string& format = " " ) {
200- return plot<double ,double >(x,y,format);
201- }
202-
203- bool plot (const std::vector<double >& y, const std::string& format = " " ) {
204- return plot<double >(y,format);
205- }
206-
207- bool plot (const std::vector<double >& x, const std::vector<double >& y, const std::map<std::string, std::string>& keywords) {
208- return plot<double >(x,y,keywords);
209- }
210-
211- bool named_plot (const std::string& name, const std::vector<double >& x, const std::vector<double >& y, const std::string& format = " " ) {
212- return named_plot<double >(name,x,y,format);
213- }
214203
215204 inline void legend () {
216205 PyObject* res = PyObject_CallObject (detail::_interpreter::get ().s_python_function_legend , detail::_interpreter::get ().s_python_empty_tuple );
@@ -255,15 +244,31 @@ namespace matplotlibcpp {
255244 Py_DECREF (res);
256245 }
257246
258- inline void show () {
247+ inline void show ()
248+ {
259249 PyObject* res = PyObject_CallObject (detail::_interpreter::get ().s_python_function_show , detail::_interpreter::get ().s_python_empty_tuple );
260250 if (!res) throw std::runtime_error (" Call to show() failed." );
261251
262252 Py_DECREF (res);
263253 }
264254
255+ inline void save (const std::string& filename)
256+ {
257+ PyObject* pyfilename = PyString_FromString (filename.c_str ());
258+
259+ PyObject* args = PyTuple_New (1 );
260+ PyTuple_SetItem (args, 0 , pyfilename);
261+
262+ PyObject* res = PyObject_CallObject (detail::_interpreter::get ().s_python_function_save , args);
263+ if (!res) throw std::runtime_error (" Call to save() failed." );
264+
265+ Py_DECREF (pyfilename);
266+ Py_DECREF (args);
267+ Py_DECREF (res);
268+ }
269+
265270#if __cplusplus > 199711L
266- // C++11-exclusive content starts here, in particular the variadic plot()
271+ // C++11-exclusive content starts here ( variadic plot() and initializer list support )
267272
268273 namespace detail {
269274 template <typename T>
@@ -302,7 +307,7 @@ namespace matplotlibcpp {
302307 struct is_callable
303308 {
304309 // dispatch to is_callable_impl<true, T> or is_callable_impl<false, T> depending on whether T is of class type or not
305- typedef typename is_callable_impl<std::is_class<T>::value, T>::type type; // todo: restore remove_reference
310+ typedef typename is_callable_impl<std::is_class<T>::value, T>::type type;
306311 };
307312
308313 template <typename IsYDataCallable>
@@ -314,7 +319,7 @@ namespace matplotlibcpp {
314319 template <typename IterableX, typename IterableY>
315320 bool operator ()(const IterableX& x, const IterableY& y, const std::string& format)
316321 {
317- // It's annoying that we have to repeat the code of plot() above
322+ // 2-phase lookup for distance, begin, end
318323 using std::distance;
319324 using std::begin;
320325 using std::end;
@@ -378,6 +383,26 @@ namespace matplotlibcpp {
378383 return detail::plot_impl<typename detail::is_callable<B>::type>()(a,b,format) && plot (args...);
379384 }
380385
386+ /*
387+ * This group of plot() functions is needed to support initializer lists, i.e. calling
388+ * plot( {1,2,3,4} )
389+ */
390+ bool plot (const std::vector<double >& x, const std::vector<double >& y, const std::string& format = " " ) {
391+ return plot<double ,double >(x,y,format);
392+ }
393+
394+ bool plot (const std::vector<double >& y, const std::string& format = " " ) {
395+ return plot<double >(y,format);
396+ }
397+
398+ bool plot (const std::vector<double >& x, const std::vector<double >& y, const std::map<std::string, std::string>& keywords) {
399+ return plot<double >(x,y,keywords);
400+ }
401+
402+ bool named_plot (const std::string& name, const std::vector<double >& x, const std::vector<double >& y, const std::string& format = " " ) {
403+ return named_plot<double >(name,x,y,format);
404+ }
405+
381406#endif
382407
383408
0 commit comments