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