From e2ceacfc4fd2ea2beb7fd9c5e3e93821f2d875f3 Mon Sep 17 00:00:00 2001 From: caremoli Date: Thu, 8 Nov 2007 17:38:47 +0000 Subject: [PATCH] CCAR: add numpy API to Datastream DSC ports --- doc/salome/tui/Makefile.am | 3 +- idl/SALOME_ModuleCatalog.idl | 43 ++- resources/KERNELCatalog.xml.in | 24 ++ salome_adm/unix/config_files/check_omniorb.m4 | 24 +- salome_adm/unix/config_files/check_swig.m4 | 7 + src/DSC/DSC_Python/Makefile.am | 4 +- src/DSC/DSC_Python/calcium.i | 360 +++++++++++++++++- 7 files changed, 430 insertions(+), 35 deletions(-) diff --git a/doc/salome/tui/Makefile.am b/doc/salome/tui/Makefile.am index 055ae5c17..12a714b16 100644 --- a/doc/salome/tui/Makefile.am +++ b/doc/salome/tui/Makefile.am @@ -51,7 +51,8 @@ usr_docs: # $(INSTALL) -d $(docdir)/tui/KERNEL; cp -fr $(srcdir)/KERNEL/sources/static/*.* $(docdir); cp -fr $(srcdir)/KERNEL/sources/ $(docdir); - cp -fr KERNEL/*.* $(docdir) + cp -fr KERNEL/[a-l]*.* $(docdir) + cp -fr KERNEL/[m-z]*.* $(docdir) cp -fr $(srcdir)/KERNEL/HTML/ $(docdir); cp -f $(srcdir)/pythfilter.py $(docdir); cp -fr $(srcdir)/KERNEL/exemple/ $(docdir); diff --git a/idl/SALOME_ModuleCatalog.idl b/idl/SALOME_ModuleCatalog.idl index 27f81b0f6..2411a98b0 100644 --- a/idl/SALOME_ModuleCatalog.idl +++ b/idl/SALOME_ModuleCatalog.idl @@ -87,6 +87,40 @@ The list of the parameters of service. typedef sequence ListOfServicesParameter; typedef sequence ListOfServicesDataStreamParameter; + typedef sequence ListOfString; + enum TypeKind + { + NONE , + Dble , + Int , + Str , + Bool , + Objref , + Seq , + Array , + Struc + }; + struct MemberDefinition + { + string name; /*! Name of the member */ + string type; /*! Type of the member */ + }; + typedef sequence ListOfMemberDefinition; +/*! + * Struct to get the definition of types used in Salome catalogs + */ + struct TypeDefinition + { + string name; /*! Name of the type */ + TypeKind kind; /*! Kind of the type.*/ + string id; /*! id (if needed) */ + string content; /*! Content type (if needed) */ + ListOfString bases; /*! Content type (if needed) */ + ListOfMemberDefinition members; /*! Members types (if needed) */ + }; + + typedef sequence ListOfTypeDefinition; + /*! This struct contains fields completely defining each service. */ @@ -143,7 +177,7 @@ List of path prefixes /*! Description of a component */ - struct Component + struct ComponentDef { ComponentType type; string name; @@ -303,6 +337,11 @@ This interface is used for creation of the module catalog in %SALOME application { void ping(); +/*! + * Get the types of the catalog + */ + ListOfTypeDefinition GetTypes(); + /*! Gets a list of names of computers of the catalog */ @@ -337,7 +376,7 @@ Gets one component of the catalog. /*! Gets the description of a component of the catalog. */ - Component GetComponentInfo(in string componentName) raises(NotFound); + ComponentDef GetComponentInfo(in string componentName) raises(NotFound); /*! Reads a xml file and imports new components from this file. diff --git a/resources/KERNELCatalog.xml.in b/resources/KERNELCatalog.xml.in index 02afa4055..347458ed4 100644 --- a/resources/KERNELCatalog.xml.in +++ b/resources/KERNELCatalog.xml.in @@ -8,6 +8,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/salome_adm/unix/config_files/check_omniorb.m4 b/salome_adm/unix/config_files/check_omniorb.m4 index 3ad61129a..f82428747 100644 --- a/salome_adm/unix/config_files/check_omniorb.m4 +++ b/salome_adm/unix/config_files/check_omniorb.m4 @@ -61,31 +61,31 @@ then OMNIORB_CXXFLAGS="-DOMNIORB_VERSION=$OMNIORB_VERSION" case $build_cpu in sparc*) - AC_DEFINE(__sparc__) + # AC_DEFINE(__sparc__) OMNIORB_CXXFLAGS="$OMNIORB_CXXFLAGS -D__sparc__" ;; *86*) - AC_DEFINE(__x86__) + # AC_DEFINE(__x86__) OMNIORB_CXXFLAGS="$OMNIORB_CXXFLAGS -D__x86__" ;; esac case $build_os in osf*) - AC_DEFINE(__osf1__) + # AC_DEFINE(__osf1__) __OSVERSION__=5 - AC_DEFINE(__OSVERSION__) + AC_DEFINE([__OSVERSION__], [5], [Description]) OMNIORB_CXXFLAGS="$OMNIORB_CXXFLAGS -D__osf1__" ;; solaris*) - AC_DEFINE(__sunos__) + # AC_DEFINE(__sunos__) __OSVERSION__=5 - AC_DEFINE(__OSVERSION__) + AC_DEFINE([__OSVERSION__], [5], [Description]) OMNIORB_CXXFLAGS="$OMNIORB_CXXFLAGS -D__sunos__" ;; linux*) - AC_DEFINE(__linux__) + # AC_DEFINE(__linux__) __OSVERSION__=2 - AC_DEFINE(__OSVERSION__) + AC_DEFINE([__OSVERSION__], [2], [Description]) OMNIORB_CXXFLAGS="$OMNIORB_CXXFLAGS -D__linux__" ;; esac @@ -214,15 +214,15 @@ then AC_SUBST(OMNIORB_IDL_TIE_H) AC_SUBST(OMNIORB_IDL_TIE_CXX) - AC_DEFINE(OMNIORB) + AC_DEFINE([OMNIORB], [], [Description]) CORBA_HAVE_POA=1 - AC_DEFINE(CORBA_HAVE_POA) + AC_DEFINE([CORBA_HAVE_POA], [], [Description]) CORBA_ORB_INIT_HAVE_3_ARGS=1 - AC_DEFINE(CORBA_ORB_INIT_HAVE_3_ARGS) + AC_DEFINE([CORBA_ORB_INIT_HAVE_3_ARGS], [], [Description]) CORBA_ORB_INIT_THIRD_ARG='"omniORB"' - AC_DEFINE(CORBA_ORB_INIT_THIRD_ARG, "omniORB") + AC_DEFINE([CORBA_ORB_INIT_THIRD_ARG], [], [omniORB]) fi diff --git a/salome_adm/unix/config_files/check_swig.m4 b/salome_adm/unix/config_files/check_swig.m4 index db9d234e9..019755067 100644 --- a/salome_adm/unix/config_files/check_swig.m4 +++ b/salome_adm/unix/config_files/check_swig.m4 @@ -57,6 +57,13 @@ EOF AC_MSG_RESULT($swig_ok) fi +numpydir=`$PYTHON -c "import numpy;print numpy.get_include()" 2>/dev/null` +if test -d "$numpydir"; then + SWIG_FLAGS="$SWIG_FLAGS -DWITH_NUMPY" + PYTHON_INCLUDES="$PYTHON_INCLUDES -I$numpydir" + AC_DEFINE([WITH_NUMPY], [], [Python has numpy extension]) +fi + AC_SUBST(SWIG_FLAGS) AC_SUBST(SWIG) diff --git a/src/DSC/DSC_Python/Makefile.am b/src/DSC/DSC_Python/Makefile.am index 48ed93f93..a40629e79 100644 --- a/src/DSC/DSC_Python/Makefile.am +++ b/src/DSC/DSC_Python/Makefile.am @@ -59,7 +59,7 @@ COMMON_LIBS = @CORBA_LIBS@ AM_CFLAGS = -fexceptions pkgpython_PYTHON = calcium.py dsccalcium.py pkgpyexec_LTLIBRARIES = _calcium.la -SWIG_FLAGS= -python -c++ -noexcept +MY_SWIG_FLAGS= $(SWIG_FLAGS) -noexcept SWIG_SRC=calcium.i _calcium_la_SOURCES = calcium_wrap.cpp _calcium_la_LDFLAGS = -module @@ -73,7 +73,7 @@ _calcium_la_LIBADD = ../DSC_User/Datastream/Calcium/libCalciumC.la \ _calcium_la_CXXFLAGS = $(PYTHON_INCLUDES) $(COMMON_CPPFLAGS) calcium_wrap.cpp calcium.py:calcium.i - $(SWIG) $(SWIG_FLAGS) -o calcium_wrap.cpp $< + $(SWIG) $(MY_SWIG_FLAGS) -o calcium_wrap.cpp $< CLEANFILES = calcium_wrap.cpp diff --git a/src/DSC/DSC_Python/calcium.i b/src/DSC/DSC_Python/calcium.i index f7700dd20..3d093153c 100644 --- a/src/DSC/DSC_Python/calcium.i +++ b/src/DSC/DSC_Python/calcium.i @@ -9,6 +9,7 @@ %{ //C++ Includes +#include #include #include #include @@ -42,6 +43,10 @@ struct omniORBpyAPI { %{ // init section +#ifdef WITH_NUMPY + import_array() +#endif + PyObject* omnipy = PyImport_ImportModule((char*)"_omnipy"); if (!omnipy) { @@ -55,25 +60,326 @@ struct omniORBpyAPI { %} %include "carrays.i" -%include "cpointer.i" - -/* Wrap a class interface around an "int *" */ -%pointer_class(int, intp); -/* Wrap a class interface around an "float *" */ -%pointer_class(float, floatp); -/* Wrap a class interface around an "double *" */ -%pointer_class(double, doublep); %array_class(int, intArray); %array_class(float, floatArray); %array_class(double, doubleArray); -%typemap(python,in) CORBA::Boolean +#ifdef WITH_NUMPY +/* + * Most of this code is borrowed from numpy distribution + * The following code originally appeared in enthought/kiva/agg/src/numeric.i, + * author unknown. It was translated from C++ to C by John Hunter. Bill + * Spotz has modified it slightly to fix some minor bugs, add some comments + * and some functionality. + */ + +%{ + +#include + +/* Macros to extract array attributes. + */ +#define is_array(a) ((a) && PyArray_Check((PyArrayObject *)a)) +#define array_type(a) (int)(PyArray_TYPE(a)) +#define array_dimensions(a) (((PyArrayObject *)a)->nd) +#define array_size(a,i) (((PyArrayObject *)a)->dimensions[i]) +#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS(a)) + +/* Given a PyObject, return a string describing its type. + */ +char* pytype_string(PyObject* py_obj) { + if (py_obj == NULL ) return "C NULL value"; + if (PyCallable_Check(py_obj)) return "callable" ; + if (PyString_Check( py_obj)) return "string" ; + if (PyInt_Check( py_obj)) return "int" ; + if (PyFloat_Check( py_obj)) return "float" ; + if (PyDict_Check( py_obj)) return "dict" ; + if (PyList_Check( py_obj)) return "list" ; + if (PyTuple_Check( py_obj)) return "tuple" ; + if (PyFile_Check( py_obj)) return "file" ; + if (PyModule_Check( py_obj)) return "module" ; + if (PyInstance_Check(py_obj)) return "instance" ; + + return "unkown type"; +} + +/* Given a Numeric typecode, return a string describing the type. + */ +char* typecode_string(int typecode) { + char* type_names[20] = {"char","unsigned byte","byte","short", + "unsigned short","int","unsigned int","long", + "float","double","complex float","complex double", + "object","ntype","unkown"}; + return type_names[typecode]; +} + +/* Make sure input has correct numeric type. Allow character and byte + * to match. Also allow int and long to match. + */ +int type_match(int actual_type, int desired_type) { + return PyArray_EquivTypenums(actual_type, desired_type); +} + +/* Given a PyObject pointer, cast it to a PyArrayObject pointer if + * legal. If not, set the python error string appropriately and + * return NULL./ + */ +PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode) { + PyArrayObject* ary = NULL; + if (is_array(input) && (typecode == PyArray_NOTYPE || + PyArray_EquivTypenums(array_type(input), + typecode))) { + ary = (PyArrayObject*) input; + } + else if is_array(input) { + char* desired_type = typecode_string(typecode); + char* actual_type = typecode_string(array_type(input)); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. Array of type '%s' given", + desired_type, actual_type); + ary = NULL; + } + else { + char * desired_type = typecode_string(typecode); + char * actual_type = pytype_string(input); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. A %s was given", + desired_type, actual_type); + ary = NULL; + } + return ary; +} + +/* Convert the given PyObject to a Numeric array with the given + * typecode. On Success, return a valid PyArrayObject* with the + * correct type. On failure, the python error string will be set and + * the routine returns NULL. + */ +PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode, + int* is_new_object) +{ + PyArrayObject* ary = NULL; + PyObject* py_obj; + if (is_array(input) && (typecode == PyArray_NOTYPE || type_match(array_type(input),typecode))) { + ary = (PyArrayObject*) input; + *is_new_object = 0; + } + else { + py_obj = PyArray_FromObject(input, typecode, 0, 0); + /* If NULL, PyArray_FromObject will have set python error value.*/ + ary = (PyArrayObject*) py_obj; + *is_new_object = 1; + } + return ary; +} + +/* Given a PyArrayObject, check to see if it is contiguous. If so, + * return the input pointer and flag it as not a new object. If it is + * not contiguous, create a new PyArrayObject using the original data, + * flag it as a new object and return the pointer. + */ +PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object, + int min_dims, int max_dims) +{ + PyArrayObject* result; + if (array_is_contiguous(ary)) { + result = ary; + *is_new_object = 0; + } + else { + result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, + array_type(ary), + min_dims, + max_dims); + *is_new_object = 1; + } + return result; +} + +/* Convert a given PyObject to a contiguous PyArrayObject of the + * specified type. If the input object is not a contiguous + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ +PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode, + &is_new1); + if (ary1) { + ary2 = make_contiguous(ary1, &is_new2, 0, 0); + if ( is_new1 && is_new2) { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; +} + +/* Test whether a python object is contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ +int require_contiguous(PyArrayObject* ary) { + int contiguous = 1; + if (!array_is_contiguous(ary)) { + PyErr_SetString(PyExc_TypeError, "Array must be contiguous. A discontiguous array was given"); + contiguous = 0; + } + return contiguous; +} + +/* Require the given PyArrayObject to have a specified number of + * dimensions. If the array has the specified number of dimensions, + * return 1. Otherwise, set the python error string and return 0. + */ +int require_dimensions(PyArrayObject* ary, int exact_dimensions) { + int success = 1; + if (array_dimensions(ary) != exact_dimensions) { + PyErr_Format(PyExc_TypeError, + "Array must have %d dimensions. Given array has %d dimensions", + exact_dimensions, array_dimensions(ary)); + success = 0; + } + return success; +} + +/* Require the given PyArrayObject to have one of a list of specified + * number of dimensions. If the array has one of the specified number + * of dimensions, return 1. Otherwise, set the python error string + * and return 0. + */ +int require_dimensions_n(PyArrayObject* ary, int* exact_dimensions, int n) { + int success = 0; + int i; + char dims_str[255] = ""; + char s[255]; + for (i = 0; i < n && !success; i++) { + if (array_dimensions(ary) == exact_dimensions[i]) { + success = 1; + } + } + if (!success) { + for (i = 0; i < n-1; i++) { + sprintf(s, "%d, ", exact_dimensions[i]); + strcat(dims_str,s); + } + sprintf(s, " or %d", exact_dimensions[n-1]); + strcat(dims_str,s); + PyErr_Format(PyExc_TypeError, + "Array must have %s dimensions. Given array has %d dimensions", + dims_str, array_dimensions(ary)); + } + return success; +} + +/* Require the given PyArrayObject to have a specified shape. If the + * array has the specified shape, return 1. Otherwise, set the python + * error string and return 0. + */ +int require_size(PyArrayObject* ary, int* size, int n) { + int i; + int success = 1; + int len; + char desired_dims[255] = "["; + char s[255]; + char actual_dims[255] = "["; + for(i=0; i < n;i++) { + if (size[i] != -1 && size[i] != array_size(ary,i)) { + success = 0; + } + } + if (!success) { + for (i = 0; i < n; i++) { + if (size[i] == -1) { + sprintf(s, "*,"); + } + else + { + sprintf(s, "%d,", size[i]); + } + strcat(desired_dims,s); + } + len = strlen(desired_dims); + desired_dims[len-1] = ']'; + for (i = 0; i < n; i++) { + sprintf(s, "%d,", array_size(ary,i)); + strcat(actual_dims,s); + } + len = strlen(actual_dims); + actual_dims[len-1] = ']'; + PyErr_Format(PyExc_TypeError, + "Array must have shape of %s. Given array has shape of %s", + desired_dims, actual_dims); + } + return success; +} + +%} + +/* input typemap */ +%define TYPEMAP_IN3(type,typecode) +%typemap(in) type* IN_ARRAY3 + (PyArrayObject* array=NULL, int is_new_object) { + int size[1] = {-1}; + if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor,0)) == -1) + { + array = obj_to_array_contiguous_allow_conversion($input, typecode, &is_new_object); + if (!array || !require_dimensions(array,1) || !require_size(array,size,1)) SWIG_fail; + $1 = (type*) array->data; + } +} +%typemap(freearg) type* IN_ARRAY3 { + if (is_new_object$argnum && array$argnum) Py_DECREF(array$argnum); +} +%enddef + +TYPEMAP_IN3(int, PyArray_INT) +TYPEMAP_IN3(float, PyArray_FLOAT ) +TYPEMAP_IN3(double, PyArray_DOUBLE) + +#undef TYPEMAP_IN3 + +%apply int* IN_ARRAY3 {int *val}; +%apply float* IN_ARRAY3 {float *val}; +%apply double* IN_ARRAY3 {double *val}; + +/* inplace typemaps */ + +%define TYPEMAP_INPLACE3(type,typecode) +%typemap(in) type* INPLACE_ARRAY3 (PyArrayObject* temp=NULL) { + if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor,0)) == -1) + { + temp = obj_to_array_no_conversion($input,typecode); + if (!temp || !require_contiguous(temp)) SWIG_fail; + $1 = (type*) temp->data; + } +} +%enddef + +TYPEMAP_INPLACE3(int, PyArray_INT) +TYPEMAP_INPLACE3(float, PyArray_FLOAT ) +TYPEMAP_INPLACE3(double, PyArray_DOUBLE) + +#undef TYPEMAP_INPLACE3 + +%apply int* INPLACE_ARRAY3 {int *lval}; +%apply float* INPLACE_ARRAY3 {float *lval}; +%apply double* INPLACE_ARRAY3 {double *lval}; + +#endif + +%typemap(in) CORBA::Boolean { $1=(CORBA::Boolean)PyInt_AsLong($input); } -%typemap(python,in) CORBA::ORB_ptr +%typemap(in) CORBA::ORB_ptr { try { CORBA::Object_ptr obj = api->pyObjRefToCxxObjRef($input,1); @@ -83,7 +389,8 @@ struct omniORBpyAPI { PyErr_SetString(PyExc_RuntimeError, "not a valid CORBA object ptr"); } } -%typemap(python,in) PortableServer::POA_ptr + +%typemap(in) PortableServer::POA_ptr { try { CORBA::Object_ptr obj = api->pyObjRefToCxxObjRef($input,1); @@ -94,7 +401,7 @@ struct omniORBpyAPI { } } -%typemap(python,in) Engines::Container_ptr +%typemap(in) Engines::Container_ptr { try { CORBA::Object_ptr obj = api->pyObjRefToCxxObjRef($input,1); @@ -104,7 +411,8 @@ struct omniORBpyAPI { PyErr_SetString(PyExc_RuntimeError, "not a valid CORBA object ptr"); } } -%typemap(python,in) Ports::Port_ptr + +%typemap(in) Ports::Port_ptr { try { CORBA::Object_ptr obj = api->pyObjRefToCxxObjRef($input,1); @@ -115,7 +423,7 @@ struct omniORBpyAPI { } } -%typemap(python,out) Ports::Port_ptr , Ports::PortProperties_ptr +%typemap(out) Ports::Port_ptr , Ports::PortProperties_ptr { $result = api->cxxObjRefToPyObjRef($1, 1); } @@ -224,6 +532,13 @@ class PySupervCompo:public Superv_Component_i } }; +%apply int *OUTPUT { int *nval }; +%apply float *INOUT { float *ti }; +%apply float *INPUT { float *tf }; +%apply int *INOUT { int *niter }; +%apply double *INOUT { double *ti }; +%apply double *INPUT { double *tf }; + extern "C" void create_calcium_port(Superv_Component_i* compo,char* name,char* type,char *mode,char* depend); #define CP_TEMPS 40 @@ -232,10 +547,19 @@ extern "C" void create_calcium_port(Superv_Component_i* compo,char* name,char* t #define CP_CONT 20 #define CP_ARRET 21 -int cp_een(void *component,int dep,float t,int n,char *nom,int nval,int *val); -int cp_edb(void *component,int dep,double t,int n,char *nom,int nval,double *val); +int cp_cd(void *component,char *name); + +int cp_een(void *component,int dep,float t,int n,char *nom,int nval,int *eval); +int cp_edb(void *component,int dep,double t,int n,char *nom,int nval,double *eval); +int cp_ere(void *component,int dep,float t,int n,char *nom,int nval,float *eval); +int cp_ecp(void *component,int dep,float t,int n,char *nom,int nval,float *eval); +int cp_elo(void *component,int dep,float t,int n,char *nom,int nval,int *eval); + +int cp_len(void *component,int dep,float *ti,float *tf,int *niter,char *nom,int nmax,int *nval,int *lval); +int cp_ldb(void *component,int dep,double *ti,double *tf,int *niter,char *nom,int nmax,int *nval,double *lval); +int cp_lre(void *component,int dep,float *ti,float *tf,int *niter,char *nom,int nmax,int *nval,float *lval); +int cp_lcp(void *component,int dep,float *ti,float *tf,int *niter,char *nom,int nmax,int *nval,float *lval); +int cp_llo(void *component,int dep,float *ti,float *tf,int *niter,char *nom,int nmax,int *nval,int *lval); -int cp_len(void *component,int dep,float *INOUT,float *INPUT,int *INOUT,char *nom,int nmax,int *OUTPUT,int *val); -int cp_ldb(void *component,int dep,double *INOUT,double *INPUT,int *INOUT,char *nom,int nmax,int *OUTPUT,double *val); int cp_fin(void *component,int cp_end); -- 2.39.2