From d7e5807b825fcad9819108999f568ee3474ef1a4 Mon Sep 17 00:00:00 2001
From: Thomas Moulard <thomas.moulard@gmail.com>
Date: Wed, 14 Mar 2012 17:24:36 +0100
Subject: [PATCH] Make bindings more robust to exceptions.

---
 src/dynamic-graph-py.cc | 17 ++++--------
 src/entity-py.cc        | 33 ++++++++--------------
 src/exception.hh        | 36 ++++++++++++++++++++++++
 src/pool-py.cc          |  7 ++---
 src/signal-base-py.cc   | 61 ++++++++++-------------------------------
 5 files changed, 71 insertions(+), 83 deletions(-)
 create mode 100644 src/exception.hh

diff --git a/src/dynamic-graph-py.cc b/src/dynamic-graph-py.cc
index e49f5ed..b69b26e 100644
--- a/src/dynamic-graph-py.cc
+++ b/src/dynamic-graph-py.cc
@@ -22,6 +22,8 @@
 #include <dynamic-graph/exception-factory.h>
 #include <dynamic-graph/signal-base.h>
 
+#include "exception.hh"
+
 namespace dynamicgraph {
   namespace python {
 
@@ -97,10 +99,7 @@ namespace dynamicgraph {
 
       try {
 	signalIn->plug(signalOut);
-      } catch (std::exception& exc) {
-	PyErr_SetString(dgpyError, exc.what());
-	return NULL;
-      }
+      } CATCH_ALL_EXCEPTIONS();
       return Py_BuildValue("");
     }
 
@@ -120,17 +119,11 @@ namespace dynamicgraph {
 	if (PyObject_IsTrue(boolean)) {
 	  try {
 	    DebugTrace::openFile(filename);
-	  } catch (const std::exception& exc) {
-	    PyErr_SetString(PyExc_IOError, exc.what());
-	    return NULL;
-	  }
+	  } CATCH_ALL_EXCEPTIONS();
 	} else {
 	  try {
 	    DebugTrace::closeFile(filename);
-	  } catch (const std::exception& exc) {
-	    PyErr_SetString(PyExc_IOError, exc.what());
-	    return NULL;
-	  }
+	  } CATCH_ALL_EXCEPTIONS();
 	}
       } else {
 	return NULL;
diff --git a/src/entity-py.cc b/src/entity-py.cc
index 53f05c2..558458b 100644
--- a/src/entity-py.cc
+++ b/src/entity-py.cc
@@ -18,12 +18,14 @@
 
 #include <dynamic-graph/entity.h>
 #include <dynamic-graph/factory.h>
-#include <../src/convert-dg-to-py.hh>
 
 #include <dynamic-graph/command.h>
 #include <dynamic-graph/value.h>
 #include <dynamic-graph/pool.h>
 
+#include "convert-dg-to-py.hh"
+#include "exception.hh"
+
 using dynamicgraph::Entity;
 using dynamicgraph::SignalBase;
 using dynamicgraph::command::Command;
@@ -71,10 +73,7 @@ namespace dynamicgraph {
 	    try {
 	      obj = dynamicgraph::FactoryStorage::getInstance()->newEntity
 		(std::string(className), std::string(instanceName));
-	    } catch (std::exception& exc) {
-	      PyErr_SetString(dgpyError, exc.what());
-	      return NULL;
-	    }
+	    } CATCH_ALL_EXCEPTIONS();
 	  }
 
 	// Return the pointer as a PyCObject
@@ -103,10 +102,7 @@ namespace dynamicgraph {
 
 	try {
 	 name = entity->getName();
-	} catch(const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS();
 	return Py_BuildValue("s", name.c_str());
       }
 
@@ -134,10 +130,8 @@ namespace dynamicgraph {
 	SignalBase<int>* signal = NULL;
 	try {
 	  signal = &(entity->getSignal(std::string(name)));
-	} catch(const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS();
+
 	// Return the pointer to the signal without destructor since the signal
 	// is not owned by the calling object but by the Entity.
 	return PyCObject_FromVoidPtr((void*)signal, NULL);
@@ -171,10 +165,7 @@ namespace dynamicgraph {
 	    count++;
 	  }
 	  return result;
-	} catch(const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS();
 	return NULL;
       }
 
@@ -238,16 +229,16 @@ namespace dynamicgraph {
 	       << exc.what() << ".";
 	    PyErr_SetString(dgpyError, ss.str().c_str()) ;
 	    return NULL;
+	  } catch (...) {
+	    PyErr_SetString(dgpyError, "Unknown exception");
+	    return NULL;
 	  }
 	}
 	command->setParameterValues(valueVector);
 	try {
 	  Value result = command->execute();
 	  return valueToPython(result);
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what()) ;
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS();
 	return NULL;
       }
 
diff --git a/src/exception.hh b/src/exception.hh
new file mode 100644
index 0000000..fddd422
--- /dev/null
+++ b/src/exception.hh
@@ -0,0 +1,36 @@
+// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
+//
+// This file is part of dynamic-graph-python.
+// dynamic-graph-python is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either
+// version 3 of the License, or (at your option) any later version.
+//
+// dynamic-graph-python is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Lesser Public License for more details.  You should
+// have received a copy of the GNU Lesser General Public License along
+// with dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef DYNAMIC_GRAPH_PYTHON_EXCEPTION
+# define DYNAMIC_GRAPH_PYTHON_EXCEPTION
+
+/// \brief Catch all exceptions which may be sent when C++ code is
+/// called.
+# define CATCH_ALL_EXCEPTIONS()					\
+  catch (const std::exception& exc)				\
+    {								\
+      PyErr_SetString(dgpyError, exc.what());			\
+      return NULL;						\
+    }								\
+  catch (const char* s)						\
+    {								\
+      PyErr_SetString(dgpyError, s);				\
+      return NULL;						\
+    } catch (...) {						\
+    PyErr_SetString(dgpyError, "Unknown exception");		\
+    return NULL;						\
+  } struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n
+
+#endif //! DYNAMIC_GRAPH_PYTHON_EXCEPTION
diff --git a/src/pool-py.cc b/src/pool-py.cc
index a879f96..1858c96 100644
--- a/src/pool-py.cc
+++ b/src/pool-py.cc
@@ -16,6 +16,8 @@
 #include <Python.h>
 #include <dynamic-graph/pool.h>
 
+#include "exception.hh"
+
 namespace dynamicgraph {
   namespace python {
 
@@ -28,10 +30,7 @@ namespace dynamicgraph {
 	  return NULL;
 	try {
 	  PoolStorage::getInstance()->writeGraph (filename);
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS();
 	return Py_BuildValue ("");
       }
     } // python
diff --git a/src/signal-base-py.cc b/src/signal-base-py.cc
index bbbf8db..fc3eddf 100644
--- a/src/signal-base-py.cc
+++ b/src/signal-base-py.cc
@@ -21,7 +21,9 @@
 #include <dynamic-graph/signal.h>
 #include <dynamic-graph/signal-caster.h>
 #include <dynamic-graph/linear-algebra.h>
-#include <../src/convert-dg-to-py.hh>
+
+#include "convert-dg-to-py.hh"
+#include "exception.hh"
 
 using dynamicgraph::SignalBase;
 
@@ -112,10 +114,8 @@ namespace dynamicgraph {
 	std::ostringstream oss;
 	try {
 	  obj->display(oss);
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS ();
+
 	return Py_BuildValue("s", oss.str().c_str());
       }
 
@@ -135,10 +135,7 @@ namespace dynamicgraph {
 	std::ostringstream oss;
 	try {
 	  obj->displayDependencies(oss,time);
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS ();
 	return Py_BuildValue("s", oss.str().c_str());
       }
 
@@ -176,24 +173,14 @@ namespace dynamicgraph {
 	    {
 	      return Py_BuildValue("d", sigdouble->accessCopy() );
 	    }
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	} catch (...) {
-	  PyErr_SetString(dgpyError, "Unknown exception");
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS ();
+
 	/* Non specific signal: use a generic way. */
 	std::ostringstream value;
 	try {
 	  signal->get(value);
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	} catch (...) {
-	  PyErr_SetString(dgpyError, "Unknown exception");
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS ();
+
 	std::string valueString = value.str();
 	return Py_BuildValue("s", valueString.c_str());
       }
@@ -213,13 +200,8 @@ namespace dynamicgraph {
 	std::string name;
 	try {
 	  name = signal->getName();
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	} catch (...) {
-	  PyErr_SetString(dgpyError, "Unknown exception");
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS ();
+
 	return Py_BuildValue("s", name.c_str());
       }
 
@@ -242,14 +224,7 @@ namespace dynamicgraph {
 
 	try {
 	  signal->set(value);
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	} catch (...) {
-	  PyErr_SetString(dgpyError, "Unknown exception");
-	  return NULL;
-	}
-
+	} CATCH_ALL_EXCEPTIONS ();
 	return Py_BuildValue("");
       }
 
@@ -267,10 +242,7 @@ namespace dynamicgraph {
 	SignalBase<int>* signal = (SignalBase<int>*)pointer;
 	try {
 	  signal->recompute(time);
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS ();
 	return Py_BuildValue("");
       }
 
@@ -287,10 +259,7 @@ namespace dynamicgraph {
 	SignalBase<int>* signal = (SignalBase<int>*)pointer;
 	try {
 	  signal->unplug();
-	} catch (const std::exception& exc) {
-	  PyErr_SetString(dgpyError, exc.what());
-	  return NULL;
-	}
+	} CATCH_ALL_EXCEPTIONS ();
 	return Py_BuildValue("");
       }
     }
-- 
GitLab