From ff6fc7dbe45a1f4f07da168e98889e1d13b5cf17 Mon Sep 17 00:00:00 2001
From: florent <florent@laas.fr>
Date: Mon, 28 Jun 2010 20:48:05 +0200
Subject: [PATCH] Implement bindings for Entity and SignalBase C++ classes.

	  * src/CMakeLists.txt,
	  * src/dynamic-graph-py.cc,
	  * src/dynamic_graph/__init__.py,
	  * src/dynamic_graph/entity.py: new,
	  * src/dynamic_graph/signal_base.py: new,
	  * src/entity-py.cc: new,
	  * src/signal-base-py.cc: new.
---
 src/CMakeLists.txt               |   7 +-
 src/dynamic-graph-py.cc          | 124 +++++++++++++++++++++-------
 src/dynamic_graph/__init__.py    |   1 +
 src/dynamic_graph/entity.py      |  39 +++++++++
 src/dynamic_graph/signal_base.py |  32 ++++++++
 src/entity-py.cc                 | 135 +++++++++++++++++++++++++++++++
 src/signal-base-py.cc            |  67 +++++++++++++++
 7 files changed, 376 insertions(+), 29 deletions(-)
 create mode 100644 src/dynamic_graph/entity.py
 create mode 100644 src/dynamic_graph/signal_base.py
 create mode 100644 src/entity-py.cc
 create mode 100644 src/signal-base-py.cc

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a85a9bf..3aae9d9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -31,7 +31,10 @@ SET(PYTHON_MODULE wrap)
 
 ADD_LIBRARY(${PYTHON_MODULE}
 	MODULE
-	dynamic-graph-py.cc)
+	dynamic-graph-py.cc
+	signal-base-py.cc
+	entity-py.cc
+)
 
 # Remove prefix lib
 SET_TARGET_PROPERTIES(${PYTHON_MODULE}
@@ -58,6 +61,8 @@ INSTALL(TARGETS ${PYTHON_MODULE}
 
 SET (PYTHON_SOURCES
     dynamic_graph/__init__.py
+    dynamic_graph/entity.py
+    dynamic_graph/signal_base.py
 )
 
 SET (PYTHON_SOURCES_FULLPATH "")
diff --git a/src/dynamic-graph-py.cc b/src/dynamic-graph-py.cc
index 54a4eb1..a8b08a1 100644
--- a/src/dynamic-graph-py.cc
+++ b/src/dynamic-graph-py.cc
@@ -8,40 +8,107 @@
 #include <sstream>
 #include <string>
 
+#include <dynamic-graph/exception-factory.h>
 #include <dynamic-graph/interpreter.h>
+#include <dynamic-graph/shell-functions.h>
 
-static PyObject* error;
+namespace dynamicgraph {
+  namespace python {
 
-static dynamicgraph::Interpreter interpreter;
+    // Declare functions defined in other source files
+    namespace signalBase {
+      extern PyObject* create(PyObject* self, PyObject* args);
+      extern PyObject* getTime(PyObject* self, PyObject* args);
+    }
+    namespace entity {
+      extern PyObject* create(PyObject* self, PyObject* args);
+      extern PyObject* getName(PyObject* self, PyObject* args);
+      extern PyObject* getSignal(PyObject* self, PyObject* args);
+      extern PyObject* displaySignals(PyObject* self, PyObject* args);
 
-static PyObject*
-plug(PyObject* self, PyObject* args)
-{
-  char* out = NULL;
-  char* in = NULL;
-  if (!PyArg_ParseTuple(args,"ss", &out, &in))
-    return NULL;
-
-  std::stringstream ss;
-  std::ostringstream os;
-  ss << std::string(out) << " " << std::string(in);
-  std::istringstream cmdArg(ss.str());
-  try {
-    interpreter.cmdPlug(std::string("plug"), cmdArg, os);
-  } catch (dynamicgraph::ExceptionFactory& exc) {
-    PyErr_SetString(error, exc.getStringMessage().c_str());
-    return NULL;
-  }
+    }
+
+    PyObject* error;
+
+    static dynamicgraph::Interpreter interpreter;
+
+    /**
+       \brief plug a signal into another one.
+    */
+    PyObject*
+    plug(PyObject* self, PyObject* args)
+    {
+      char* out = NULL;
+      char* in = NULL;
+      if (!PyArg_ParseTuple(args,"ss", &out, &in))
+	return NULL;
+
+      std::stringstream ss;
+      std::ostringstream os;
+      ss << std::string(out) << " " << std::string(in);
+      std::istringstream cmdArg(ss.str());
+      try {
+	interpreter.cmdPlug(std::string("plug"), cmdArg, os);
+      } catch (dynamicgraph::ExceptionFactory& exc) {
+	PyErr_SetString(error, exc.getStringMessage().c_str());
+	return NULL;
+      }
 
-  return Py_BuildValue("");
+      return Py_BuildValue("");
+    }
+
+    PyObject*
+    enableTrace(PyObject* self, PyObject* args)
+    {
+      char* trueFalse = NULL;
+      char* filename = NULL;
+      std::stringstream ss;
+      std::ostringstream os;
+
+      if (PyArg_ParseTuple(args,"ss", &trueFalse, &filename)) {
+	ss << std::string(trueFalse) << " " << std::string(filename);
+      } else if (PyArg_ParseTuple(args,"s", &trueFalse)) {
+	ss << std::string(trueFalse);
+      } else {
+	return NULL;
+      }
+
+      std::istringstream cmdArg(ss.str());
+      try {
+	ShellFunctions::cmdEnableTrace(std::string("debugtrace"), cmdArg, os);
+      } catch (dynamicgraph::ExceptionFactory& exc) {
+	PyErr_SetString(error, exc.getStringMessage().c_str());
+	return NULL;
+      }
+
+      return Py_BuildValue("");
+    }
+  }
 }
 
 /**
    \brief List of python functions
 */
-static PyMethodDef sotTutorialMethods[] = {
-  {"plug",  plug, METH_VARARGS,
-     "plug an output signal into an input signal"},
+static PyMethodDef dynamicGraphMethods[] = {
+  {"plug",  dynamicgraph::python::plug, METH_VARARGS,
+   "plug an output signal into an input signal"},
+  {"debugtrace",  dynamicgraph::python::enableTrace, METH_VARARGS,
+   "Enable or disable tracing debug info in a file"},
+  // Signals
+  {"create_signal_base", dynamicgraph::python::signalBase::create, METH_VARARGS,
+   "create a SignalBase C++ object"},
+  {"signalbase_get_time", dynamicgraph::python::signalBase::getTime,
+   METH_VARARGS, "Get time of  a SignalBase"},
+  // Entity
+  {"create_entity", dynamicgraph::python::entity::create, METH_VARARGS,
+   "create an Entity C++ object"},
+  {"entity_get_name", dynamicgraph::python::entity::getName, METH_VARARGS,
+   "get the name of an Entity"},
+  {"entity_get_signal", dynamicgraph::python::entity::getSignal, METH_VARARGS,
+   "get signal by name from an Entity"},
+  {"entity_display_signals", dynamicgraph::python::entity::displaySignals,
+   METH_VARARGS,
+   "Display the list of signals of an entity in standard output"},
   {NULL, NULL, 0, NULL}        /* Sentinel */
 };
 
@@ -50,11 +117,12 @@ initwrap(void)
 {
     PyObject *m;
 
-    m = Py_InitModule("wrap", sotTutorialMethods);
+    m = Py_InitModule("wrap", dynamicGraphMethods);
     if (m == NULL)
         return;
 
-    error = PyErr_NewException("dynamic_graph.wrap.error", NULL, NULL);
-    Py_INCREF(error);
-    PyModule_AddObject(m, "error", error);
+    dynamicgraph::python::error =
+      PyErr_NewException("dynamic_graph.wrap.error", NULL, NULL);
+    Py_INCREF(dynamicgraph::python::error);
+    PyModule_AddObject(m, "error", dynamicgraph::python::error);
 }
diff --git a/src/dynamic_graph/__init__.py b/src/dynamic_graph/__init__.py
index 0209bd5..9f831c4 100644
--- a/src/dynamic_graph/__init__.py
+++ b/src/dynamic_graph/__init__.py
@@ -4,3 +4,4 @@ Author: Florent Lamiraux
 """
 
 import wrap
+import entity, signal_base
diff --git a/src/dynamic_graph/entity.py b/src/dynamic_graph/entity.py
new file mode 100644
index 0000000..fa78ccf
--- /dev/null
+++ b/src/dynamic_graph/entity.py
@@ -0,0 +1,39 @@
+"""
+  Copyright (C) 2010 CNRS
+
+  Author: Florent Lamiraux
+"""
+import wrap, signal_base
+
+class Entity:
+    """
+    This class binds dynamicgraph::Entity C++ class
+    """
+    
+    object = None
+
+    def __init__(self, name):
+        """
+        Constructor: if not called by a child class, create and store a pointer
+        to a C++ Entity object.
+        """
+        if not self.object :
+            self.object = wrap.create_entity(self, name)
+
+    @property
+    def name(self) :
+        return wrap.entity_get_name(self.object)
+
+    def get_signal (self, name) :
+        """
+        Get a signal of the entity from signal name
+        """
+        signalPt = wrap.entity_get_signal(self.object, name)
+        return signal_base.SignalBase("", signalPt)
+        
+    def display_signals(self) :
+        """
+        Write the list of signals into standard output: temporary.
+        """
+        wrap.entity_display_signals(self.object)
+
diff --git a/src/dynamic_graph/signal_base.py b/src/dynamic_graph/signal_base.py
new file mode 100644
index 0000000..17d9b33
--- /dev/null
+++ b/src/dynamic_graph/signal_base.py
@@ -0,0 +1,32 @@
+"""
+  Copyright (C) 2010 CNRS
+
+  Author: Florent Lamiraux
+"""
+import wrap
+
+class SignalBase:
+    """
+    This class binds dynamicgraph::SignalBase<int> C++ class
+    """
+    def __init__(self, name, object = None) :
+        """
+        Constructor: create and store a pointer to a C++ Entity object if
+          - the constructor is not called by a child class and
+          - object parameter is not provided.
+        If object parameter is provided, the class wraps an already existing
+        C++ object.
+        """
+        if object is None :
+            if not hasattr(self, "object") :
+                self.object = wrap.create_signal_base(name)
+        else :
+            self.object = object
+
+    @property
+    def time(self) :
+        """
+        Get time of signal
+        """
+        return wrap.signalBaseGetTime(self.object)
+
diff --git a/src/entity-py.cc b/src/entity-py.cc
new file mode 100644
index 0000000..fa2fc48
--- /dev/null
+++ b/src/entity-py.cc
@@ -0,0 +1,135 @@
+/*
+ *  Copyright 2010 (C) CNRS
+ *  Author: Florent Lamiraux
+ */
+
+#include <Python.h>
+#include <iostream>
+//#include <sstream>
+//#include <string>
+
+#include <dynamic-graph/entity.h>
+
+using dynamicgraph::Entity;
+using dynamicgraph::SignalBase;
+using dynamicgraph::ExceptionAbstract;
+
+namespace dynamicgraph {
+  namespace python {
+    
+    extern PyObject* error;
+
+    namespace entity {
+      
+      static void destroy (void* self);
+      /**
+	 \brief Create an instance of Entity
+      */
+      PyObject* create(PyObject* self, PyObject* args)
+      {
+	char *name = NULL;
+	
+	if (!PyArg_ParseTuple(args, "s", &name))
+	  return NULL;
+	
+	Entity* obj = NULL;
+	try {
+	  obj = new Entity(name);
+	} catch (dynamicgraph::ExceptionFactory& exc) {
+	  PyErr_SetString(error, exc.getStringMessage().c_str());
+	  return NULL;
+	}
+	
+	// Return the pointer as an integer
+	return PyCObject_FromVoidPtr((void*)obj, destroy);
+      }
+      
+      /**
+	 \brief Destroy an instance of Entity
+      */
+      static void destroy (void* self)
+      {
+	Entity* obj = (Entity*)self;
+	delete obj;
+      }
+      
+      /**
+	 \brief Get name of entity
+      */
+      PyObject* getName(PyObject* self, PyObject* args)
+      {
+	PyObject* object = NULL;
+	void* pointer = NULL;
+	std::string name;
+
+	if (!PyArg_ParseTuple(args, "O", &object))
+	  return NULL;
+	if (!PyCObject_Check(object))
+	  return NULL;
+
+	pointer = PyCObject_AsVoidPtr(object);
+	Entity* entity = (Entity*)pointer;
+
+	try {
+	 name = entity->getName();
+	} catch(ExceptionAbstract& exc) {
+	  PyErr_SetString(error, exc.getStringMessage().c_str());
+	  return NULL;
+	}
+	return Py_BuildValue("s", name.c_str());
+      }
+
+      /**
+	 \brief Get a signal by name
+      */
+      PyObject* getSignal(PyObject* self, PyObject* args)
+      {
+	char *name = NULL;
+	PyObject* object = NULL;
+	void* pointer = NULL;
+
+	if (!PyArg_ParseTuple(args, "Os", &object, &name))
+	  return NULL;
+	
+	if (!PyCObject_Check(object))
+	  return NULL;
+
+	pointer = PyCObject_AsVoidPtr(object);
+	Entity* entity = (Entity*)pointer;
+
+	SignalBase<int>* signal = NULL;
+	try {
+	  signal = &(entity->getSignal(std::string(name)));
+	} catch(ExceptionAbstract& exc) {
+	  PyErr_SetString(error, exc.getStringMessage().c_str());
+	  return NULL;
+	}
+	// 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);
+      }
+
+      PyObject* displaySignals(PyObject* self, PyObject* args)
+      {
+	void* pointer = NULL;
+	PyObject* object = NULL;
+	
+	if (!PyArg_ParseTuple(args, "O", &object))
+	  return NULL;
+	
+	if (!PyCObject_Check(object))
+	  return NULL;
+
+	pointer = PyCObject_AsVoidPtr(object);
+	Entity* entity = (Entity*)pointer;
+	try {
+	  entity->displaySignalList(std::cout);
+	} catch(ExceptionAbstract& exc) {
+	  PyErr_SetString(error, exc.getStringMessage().c_str());
+	  return NULL;
+	}
+	return Py_BuildValue("");
+      }
+    }
+  }
+}
diff --git a/src/signal-base-py.cc b/src/signal-base-py.cc
new file mode 100644
index 0000000..a86d38b
--- /dev/null
+++ b/src/signal-base-py.cc
@@ -0,0 +1,67 @@
+/*
+ *  Copyright 2010 (C) CNRS
+ *  Author: Florent Lamiraux
+ */
+
+#include <Python.h>
+#include <iostream>
+//#include <sstream>
+//#include <string>
+
+#include <dynamic-graph/signal-base.h>
+
+using dynamicgraph::SignalBase;
+
+namespace dynamicgraph {
+  namespace python {
+
+    extern PyObject* error;
+
+    namespace signalBase {
+
+      static void destroy (void* self);
+
+      /**
+	 \brief Create an instance of SignalBase
+      */
+      PyObject* create(PyObject* self, PyObject* args)
+      {
+	char *name = NULL;
+	
+	if (!PyArg_ParseTuple(args, "s", &name))
+	  return NULL;
+	
+	SignalBase<int>* obj = NULL;
+	obj = new SignalBase<int>(std::string(name));
+	
+	// Return the pointer
+	return PyCObject_FromVoidPtr((void*)obj, destroy);
+      }
+      
+      /**
+	 \brief Destroy an instance of InvertedPendulum
+      */
+      static void destroy (void* self)
+      {
+	SignalBase<int>* obj = (SignalBase<int>*)self;
+	delete obj;
+      }
+      
+      PyObject* getTime(PyObject* self, PyObject* args)
+      {
+	void* pointer = NULL;
+	PyObject* object = NULL;
+	if (!PyArg_ParseTuple(args,"O", &object))
+	  return NULL;
+	if (!PyCObject_Check(object))
+	  return NULL;
+
+	pointer = PyCObject_AsVoidPtr(object);
+	SignalBase<int>* obj = (SignalBase<int>*)pointer;
+	
+	int time = obj->getTime();
+	return Py_BuildValue("i", time);
+      }
+    }
+  }
+}
-- 
GitLab