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