From e661bae79de8a619db506226a565f5d357b97f62 Mon Sep 17 00:00:00 2001
From: florent <florent@laas.fr>
Date: Thu, 21 Oct 2010 17:58:39 +0200
Subject: [PATCH] Implement binidings for commands

	  * src/dynamic-graph-py.cc,
	  * src/entity-py.cc.
---
 src/dynamic-graph-py.cc |   6 +-
 src/entity-py.cc        | 135 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 130 insertions(+), 11 deletions(-)

diff --git a/src/dynamic-graph-py.cc b/src/dynamic-graph-py.cc
index 5cab7d6..f2a4cac 100644
--- a/src/dynamic-graph-py.cc
+++ b/src/dynamic-graph-py.cc
@@ -27,7 +27,7 @@ namespace dynamicgraph {
       extern PyObject* getName(PyObject* self, PyObject* args);
       extern PyObject* getSignal(PyObject* self, PyObject* args);
       extern PyObject* displaySignals(PyObject* self, PyObject* args);
-
+      extern PyObject* executeCommand(PyObject* self, PyObject* args);
     }
 
     namespace factory {
@@ -117,6 +117,10 @@ static PyMethodDef dynamicGraphMethods[] = {
   {"entity_display_signals", dynamicgraph::python::entity::displaySignals,
    METH_VARARGS,
    "Display the list of signals of an entity in standard output"},
+  {"entity_execute_command",
+   dynamicgraph::python::entity::executeCommand,
+   METH_VARARGS,
+   "execute a command"},
   {"factory_get_entity_class_list",
    dynamicgraph::python::factory::getEntityClassList,
    METH_VARARGS,
diff --git a/src/entity-py.cc b/src/entity-py.cc
index cae0da2..7945bcb 100644
--- a/src/entity-py.cc
+++ b/src/entity-py.cc
@@ -11,18 +11,25 @@
 #include <dynamic-graph/entity.h>
 #include <dynamic-graph/factory.h>
 
+#include "dynamic-graph/command.h"
+#include "dynamic-graph/value.h"
+
 using dynamicgraph::Entity;
 using dynamicgraph::SignalBase;
 using dynamicgraph::ExceptionAbstract;
+using dynamicgraph::command::Command;
+using dynamicgraph::command::Value;
 
 namespace dynamicgraph {
   namespace python {
-    
+
     extern PyObject* error;
 
     namespace entity {
-      
+
       static void destroy (void* self);
+      static Value pythonToValue(PyObject* pyObject,
+					const Value::Type& valueType);
       /**
 	 \brief Create an instance of Entity
       */
@@ -30,10 +37,10 @@ namespace dynamicgraph {
       {
 	char *className = NULL;
 	char *instanceName = NULL;
-	
+
 	if (!PyArg_ParseTuple(args, "ss", &className, &instanceName))
 	  return NULL;
-	
+
 	Entity* obj = NULL;
 	try {
 	  obj = dynamicgraph::g_factory.newEntity(std::string(className),
@@ -42,11 +49,11 @@ namespace dynamicgraph {
 	  PyErr_SetString(error, exc.getStringMessage().c_str());
 	  return NULL;
 	}
-	
+
 	// Return the pointer as a PyCObject
 	return PyCObject_FromVoidPtr((void*)obj, destroy);
       }
-      
+
       /**
 	 \brief Destroy an instance of Entity
       */
@@ -55,7 +62,7 @@ namespace dynamicgraph {
 	Entity* obj = (Entity*)self;
 	delete obj;
       }
-      
+
       /**
 	 \brief Get name of entity
       */
@@ -93,7 +100,7 @@ namespace dynamicgraph {
 
 	if (!PyArg_ParseTuple(args, "Os", &object, &name))
 	  return NULL;
-	
+
 	if (!PyCObject_Check(object))
 	  return NULL;
 
@@ -116,10 +123,10 @@ namespace dynamicgraph {
       {
 	void* pointer = NULL;
 	PyObject* object = NULL;
-	
+
 	if (!PyArg_ParseTuple(args, "O", &object))
 	  return NULL;
-	
+
 	if (!PyCObject_Check(object))
 	  return NULL;
 
@@ -133,6 +140,114 @@ namespace dynamicgraph {
 	}
 	return Py_BuildValue("");
       }
+
+      Value pythonToValue(PyObject* pyObject,
+			     const Value::Type& valueType)
+      {
+	double dvalue;
+	std::string svalue;
+	int ivalue;
+
+	switch (valueType) {
+	case (Value::INT) :
+	  if (!PyLong_Check(pyObject)) {
+	    throw ExceptionFactory(ExceptionFactory::GENERIC,
+				   "float");
+	  }
+	  ivalue = (int)PyLong_AsLong(pyObject);
+	  std::cout << "int value = " << ivalue << std::endl;
+	  return Value(ivalue);
+	  break;
+	case (Value::DOUBLE) :
+	  if (!PyFloat_Check(pyObject)) {
+	    throw ExceptionFactory(ExceptionFactory::GENERIC,
+				   "float");
+	  }
+	  dvalue = PyFloat_AsDouble(pyObject);
+	  std::cout << "double value = " << dvalue << std::endl;
+	  return Value(dvalue);
+	  break;
+	case (Value::STRING) :
+	  svalue = PyString_AsString(pyObject);
+	  return Value(svalue);
+	  break;
+	default:
+	  std::cerr << "Only int, double and string are supported."
+		    << std::endl;
+	}
+	return Value();
+      }
+
+      PyObject* executeCommand(PyObject* self, PyObject* args)
+      {
+	PyObject* object = NULL;
+	PyObject* argTuple = NULL;
+	std::string commandName;
+	void* pointer = NULL;
+
+	if (!PyArg_ParseTuple(args, "OsO", &object, &commandName, &argTuple)) {
+	  return NULL;
+	}
+
+	// Retrieve the entity instance
+	if (!PyCObject_Check(object)) {
+	  PyErr_SetString(error, "first argument is not an object");
+	  return NULL;
+	}
+	pointer = PyCObject_AsVoidPtr(object);
+	Entity* entity = (Entity*)pointer;
+
+	// Retrieve the argument tuple
+	if (!PyTuple_Check(argTuple)) {
+	  PyErr_SetString(error, "third argument is not a tuple");
+	  return NULL;
+	}
+	unsigned int size = PyTuple_Size(argTuple);
+
+	std::map<const std::string, Command*> commandMap =
+	  entity->getNewStyleCommandMap();
+
+	if (commandMap.count(commandName) != 1) {
+	  std::string msg = "command " + commandName +
+	    " is not referenced in Entity " + entity->getName();
+	  PyErr_SetString(error, msg.c_str());
+	  return NULL;
+	}
+	Command* command = commandMap[commandName];
+	// Check that tuple size is equal to command number of arguments
+	const std::vector<Value::Type> typeVector = command->valueTypes();
+	if (size != typeVector.size()) {
+	  std::stringstream ss;
+	  ss << "command takes " <<  typeVector.size()
+	     << " parameters, " << size << " given.";
+	  PyErr_SetString(error, ss.str().c_str());
+	  return NULL;
+	}
+
+	std::vector<Value> valueVector;
+	for (unsigned int iParam=0; iParam<size; iParam++) {
+	  PyObject* PyValue = PyTuple_GetItem(argTuple, iParam);
+	  Value::Type valueType = typeVector[iParam];
+	  try {
+	    Value value = pythonToValue(PyValue, valueType);
+	    valueVector.push_back(value);
+	  } catch (ExceptionAbstract& exc) {
+	    std::stringstream ss;
+	    ss << "argument " << iParam+1 << " should be a "
+	       << exc.what() << ".";
+	    PyErr_SetString(error, ss.str().c_str()) ;
+	    return NULL;
+	  }
+	}
+	command->setParameterValues(valueVector);
+	try {
+	  command->execute();
+	} catch (const ExceptionAbstract& exc) {
+	  PyErr_SetString(error, exc.what()) ;
+	  return NULL;
+	}
+	return Py_BuildValue("");
+      }
     }
   }
 }
-- 
GitLab