]> SALOME platform Git repositories - tools/yacsgen.git/commitdiff
Salome HOME
Addition of MPIComponent
authorOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Fri, 8 Jan 2016 10:16:07 +0000 (11:16 +0100)
committerOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Fri, 8 Jan 2016 10:16:07 +0000 (11:16 +0100)
module_generator/__init__.py
module_generator/cata_tmpl.py
module_generator/cpp_tmpl.py
module_generator/cppcompo.py
module_generator/gener.py
module_generator/hxxcompo.py
module_generator/hxxparacompo.py
module_generator/mpi_tmpl.py [new file with mode: 0644]
module_generator/mpicompo.py [new file with mode: 0644]
module_generator/pacocompo.py

index 1485a3633d9938d4f1bbcb3619715cf540702556..1e91274f079b7efe30277fc54259a98a310188c4 100644 (file)
@@ -33,3 +33,4 @@ from hxxparacompo import HXX2SALOMEParaComponent
 from yacstypes import add_type
 from salomemodules import add_module
 from gener import Library
+from mpicompo import MPIComponent
index 2b48b4325dc4642d83371e30c2032ba4654cb0d6..14a88cf79efa210e4d0aac3230945d01371a7514 100644 (file)
@@ -28,12 +28,9 @@ idl="""
 #ifndef _${module}_IDL_
 #define _${module}_IDL_
 
-#include "DSC_Engines.idl"
 #include "SALOME_Exception.idl"
-#include "SALOME_PACOExtension.idl"
 #include "SALOME_Component.idl"
 #include "SALOME_Comm.idl"
-#include "SALOME_Parametric.idl"
 
 ${idldefs}
 
index 6c937e1495239908b6620701ea7e98d111491b49..ad2c65cc24b7f829d989ede365d6067e1922eff0 100644 (file)
@@ -444,11 +444,6 @@ SET(_link_LIBRARIES
   $${KERNEL_SalomeIDLKernel}
   $${KERNEL_OpUtil}
   $${KERNEL_SalomeContainer}
-  $${KERNEL_SalomeDSCContainer}
-  $${KERNEL_SalomeDSCSuperv}
-  $${KERNEL_SalomeDatastream}
-  $${KERNEL_SalomeDSCSupervBasic}
-  $${KERNEL_CalciumC}
   SalomeIDL${module}
   ${libs}
 )
index e3cfc5aa9454442372d6782c3e1b6ffe9f2c8a34..290277318e761f6d7e4755f2b3e00ab917b6ceed 100644 (file)
@@ -121,6 +121,14 @@ class CPPComponent(Component):
        return a dict where key is the file name and value is the file content
     """
     (cmake_text, cmake_vars) = self.additionalLibraries()
+    # DSC_libs are needed for datastream ports only
+    DSC_libs = """${KERNEL_SalomeDSCContainer}
+  ${KERNEL_SalomeDSCSuperv}
+  ${KERNEL_SalomeDatastream}
+  ${KERNEL_SalomeDSCSupervBasic}
+  ${KERNEL_CalciumC}
+  """
+    cmake_vars = DSC_libs + cmake_vars
     cxxfile = "%s.cxx" % self.name
     hxxfile = "%s.hxx" % self.name
     if self.kind == "exe":
index 1473b8d2dfda586e84533075db1b31be83e9d0f8..44872489abcf2688184d6829b5baa089ab64dd34 100644 (file)
@@ -32,7 +32,7 @@ class Invalid(Exception):
 debug=0
 
 from mod_tmpl import *
-from cata_tmpl import catalog, interface, idl, parallel_interface
+from cata_tmpl import catalog, interface, idl
 from cata_tmpl import xml, xml_interface, xml_service
 from cata_tmpl import idlMakefilePaCO_BUILT_SOURCES, idlMakefilePaCO_nodist_salomeinclude_HEADERS
 from cata_tmpl import idlMakefilePACO_salomepython_DATA, idlMakefilePACO_salomeidl_DATA
@@ -206,6 +206,47 @@ class Component(object):
   def setPrerequisites(self, prerequisites_file):
     self.prerequisites = prerequisites_file
 
+  def getIdlInterfaces(self):
+    services = self.getIdlServices()
+    inheritedinterface=""
+    if self.inheritedinterface:
+      inheritedinterface=self.inheritedinterface+","
+    return interface.substitute(component=self.name,
+                                services="\n".join(services),
+                                inheritedinterface=inheritedinterface)
+
+  def getIdlServices(self):
+    services = []
+    for serv in self.services:
+      params = []
+      for name, typ in serv.inport:
+        if typ == "file":continue #files are not passed through IDL interface
+        if self.impl in ("PY", "ASTER") and typ == "pyobj":
+          typ = "Engines::fileBlock"
+        else:
+          typ=idlTypes[typ]
+        params.append("in %s %s" % (typ, name))
+      for name, typ in serv.outport:
+        if typ == "file":continue #files are not passed through IDL interface
+        if self.impl in ("PY", "ASTER") and typ == "pyobj":
+          typ = "Engines::fileBlock"
+        else:
+          typ=idlTypes[typ]
+        params.append("out %s %s" % (typ, name))
+      service = "    %s %s(" % (idlTypes[serv.ret],serv.name)
+      service = service+",".join(params)+") raises (SALOME::SALOME_Exception);"
+      services.append(service)
+    return services
+
+  def getIdlDefs(self):
+    idldefs = """
+#include "DSC_Engines.idl"
+#include "SALOME_Parametric.idl"
+"""
+    if self.interfacedefs:
+      idldefs = idldefs + self.interfacedefs
+    return idldefs
+
 class Service(object):
   """
    A :class:`Service` instance represents a component service with dataflow and datastream ports.
@@ -708,77 +749,26 @@ class Generator(object):
 
   def makeidl(self):
     """generate module IDL file source (CORBA interface)"""
-    from pacocompo import PACOComponent
     interfaces = []
     idldefs=""
     for compo in self.module.components:
-      if isinstance(compo, PACOComponent):
-        services = []
-        for serv in compo.services:
-          params = []
-          for name, typ in serv.inport:
-            if typ == "file":continue #files are not passed through IDL interface
-            params.append("in %s %s" % (idlTypes[typ], name))
-          for name, typ in serv.outport:
-            if typ == "file":continue #files are not passed through IDL interface
-            params.append("out %s %s" % (idlTypes[typ], name))
-          service = "    void %s(" % serv.name
-          service = service+",".join(params)+");"
-          services.append(service)
-
-        interfaces.append(parallel_interface.substitute(component=compo.name, services="\n".join(services)))
-
-      else:
-        services = []
-        for serv in compo.services:
-          params = []
-          for name, typ in serv.inport:
-            if typ == "file":continue #files are not passed through IDL interface
-            if compo.impl in ("PY", "ASTER") and typ == "pyobj":
-              typ = "Engines::fileBlock"
-            else:
-              typ=idlTypes[typ]
-            params.append("in %s %s" % (typ, name))
-          for name, typ in serv.outport:
-            if typ == "file":continue #files are not passed through IDL interface
-            if compo.impl in ("PY", "ASTER") and typ == "pyobj":
-              typ = "Engines::fileBlock"
-            else:
-              typ=idlTypes[typ]
-            params.append("out %s %s" % (typ, name))
-          service = "    %s %s(" % (idlTypes[serv.ret],serv.name)
-          service = service+",".join(params)+") raises (SALOME::SALOME_Exception);"
-          services.append(service)
-
-        from hxxcompo import HXX2SALOMEComponent
-        from hxxparacompo import HXX2SALOMEParaComponent
-        if isinstance(compo,HXX2SALOMEComponent) or isinstance(compo,HXX2SALOMEParaComponent):
-          from hxx_tmpl import interfaceidlhxx
-          Inherited=""
-          if isinstance(compo,HXX2SALOMEParaComponent):
-              Inherited="SALOME_MED::ParaMEDMEMComponent"
-              idldefs="""#include "ParaMEDMEMComponent.idl"\n"""
-          else:
-              if compo.use_medmem==True:
-                  Inherited="Engines::EngineComponent,SALOME::MultiCommClass,SALOME_MED::MED_Gen_Driver"
-              else:
-                  Inherited="Engines::EngineComponent"
-          interfaces.append(interfaceidlhxx.substitute(component=compo.name,inherited=Inherited, services="\n".join(services)))
-        else:
-          inheritedinterface=""
-          if compo.inheritedinterface:
-            inheritedinterface=compo.inheritedinterface+","
-          interfaces.append(interface.substitute(component=compo.name, services="\n".join(services),inheritedinterface=inheritedinterface))
+      interfaces.append(compo.getIdlInterfaces())
 
     #build idl includes for SALOME modules
     for mod in self.used_modules:
       idldefs = idldefs + salome_modules[mod]["idldefs"]
 
     for compo in self.module.components:
-      if compo.interfacedefs:
-        idldefs = idldefs + compo.interfacedefs
-
-    return idl.substitute(module=self.module.name, interfaces='\n'.join(interfaces),idldefs=idldefs)
+      idldefs = idldefs + compo.getIdlDefs()
+    
+    filteredDefs = []
+    for defLine in idldefs.split('\n'):
+      if defLine not in filteredDefs:
+        filteredDefs.append(defLine)
+
+    return idl.substitute(module=self.module.name,
+                          interfaces='\n'.join(interfaces),
+                          idldefs='\n'.join(filteredDefs) )
 
   # For PaCO++
   def makexml(self):
index 94d8220e39d0bc615113a0e2f4c0359bf5966ca5..41aae0438ef3074bfdb4042de754e9561f33c846 100644 (file)
@@ -526,3 +526,14 @@ class HXX2SALOMEComponent(Component):
       gui_salomeapp_file.close()
       list_of_gui_names.append(gui_salomeapp_file_name)
       return list_of_gui_names
+
+  def getIdlInterfaces(self):
+    services = self.getIdlServices()
+    from hxx_tmpl import interfaceidlhxx
+    Inherited=""
+    if compo.use_medmem==True:
+        Inherited="Engines::EngineComponent,SALOME::MultiCommClass,SALOME_MED::MED_Gen_Driver"
+    else:
+        Inherited="Engines::EngineComponent"
+    return interfaceidlhxx.substitute(component=compo.name,inherited=Inherited, services="\n".join(services))
+
index 1d59a122eecb6103c5eea43cb484204950ba4a78..b27d0035f16bc180f6f2c5c465dd7609ff67b82c 100644 (file)
@@ -471,3 +471,10 @@ void *th_%(serv_name)s(void *s)
                                servicesimpl="\n".join(services),
                                thread_impl=self.thread_impl % {"module":gen.module.name} )
 
+  def getIdlInterfaces(self):
+    services = self.getIdlServices()
+    from hxx_tmpl import interfaceidlhxx
+    Inherited=""
+    Inherited="SALOME_MED::ParaMEDMEMComponent"
+    idldefs="""#include "ParaMEDMEMComponent.idl"\n"""
+    return interfaceidlhxx.substitute(component=compo.name,inherited=Inherited, services="\n".join(services))
diff --git a/module_generator/mpi_tmpl.py b/module_generator/mpi_tmpl.py
new file mode 100644 (file)
index 0000000..6ce3172
--- /dev/null
@@ -0,0 +1,317 @@
+# Copyright (C) 2009-2015  EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+try:
+  from string import Template
+except:
+  from compat import Template,set
+
+# cxx file of a MPI component.
+# template parameters:
+#   component : component name
+#   servicesdef : extra "#include"
+#   servicesimpl : services implementations
+cxxCompo="""
+#include "${component}.hxx"
+#include <string>
+#include <unistd.h>
+#include <signal.h>
+#include <SALOME_NamingService.hxx>
+#include <Utils_SALOME_Exception.hxx>
+#include "Utils_CorbaException.hxx"
+#include <pthread.h>
+#include <execinfo.h>
+
+typedef struct
+{
+  bool exception;
+  std::string msg;
+} exception_st;
+
+//DEFS
+${servicesdef}
+//ENDDEF
+
+
+using namespace std;
+
+//! Constructor for component "${component}" instance
+/*!
+ *
+ */
+${component}_i::${component}_i(CORBA::ORB_ptr orb,
+                     PortableServer::POA_ptr poa,
+                     PortableServer::ObjectId * contId,
+                     const char *instanceName,
+                     const char *interfaceName,
+                     bool regist)
+          : Engines_Component_i(orb, poa, contId, instanceName, interfaceName,
+                                false, regist)
+{
+  _thisObj = this ;
+  _id = _poa->activate_object(_thisObj);
+}
+
+${component}_i::${component}_i(CORBA::ORB_ptr orb,
+                     PortableServer::POA_ptr poa,
+                     Engines::Container_ptr container,
+                     const char *instanceName,
+                     const char *interfaceName,
+                     bool regist)
+          : Engines_Component_i(orb, poa, container, instanceName, interfaceName,
+                                false, regist)
+{
+  _thisObj = this ;
+  _id = _poa->activate_object(_thisObj);
+}
+
+//! Destructor for component "${component}" instance
+${component}_i::~${component}_i()
+{
+}
+
+${servicesimpl}
+
+extern "C"
+{
+  PortableServer::ObjectId * ${component}Engine_factory( CORBA::ORB_ptr orb,
+                                                    PortableServer::POA_ptr poa,
+                                                    PortableServer::ObjectId * contId,
+                                                    const char *instanceName,
+                                                    const char *interfaceName)
+  {
+    MESSAGE("PortableServer::ObjectId * ${component}Engine_factory()");
+    int is_mpi_container;
+    bool regist;
+    int numproc;
+    
+    MPI_Initialized(&is_mpi_container);
+    if (!is_mpi_container)
+    {
+      int argc = 0;
+      char ** argv = NULL;
+      MPI_Init(&argc, &argv);
+    }
+    
+    MPI_Comm_rank( MPI_COMM_WORLD, &numproc );
+    if( numproc == 0 )
+      regist = true;
+    else
+      regist = false;
+    ${component}_i * myEngine = new ${component}_i(orb, poa, contId, instanceName, interfaceName, regist);
+    return myEngine->getId() ;
+  }
+}
+"""
+cxxCompo=Template(cxxCompo)
+
+# Header file of a MPI component
+# template parameters:
+#   component : component name
+#   module : module name
+#   compodefs : additional "#include" and other specific declarations
+#   servicesdef : declaration of component services
+hxxCompo="""
+#ifndef _${component}_HXX_
+#define _${component}_HXX_
+
+#include <SALOME_Component.hh>
+#include "Superv_Component_i.hxx"
+#include "${module}.hh"
+#include "MPIObject_i.hxx"
+
+//COMPODEFS
+${compodefs}
+//ENDDEF
+
+class ${component}_i: public virtual POA_${module}_ORB::${component},
+                      ${inheritedclass}
+                      public virtual MPIObject_i,
+                      public virtual Engines_Component_i
+{
+  public:
+    ${component}_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa,
+              PortableServer::ObjectId * contId,
+              const char *instanceName, const char *interfaceName,
+              bool regist = true);
+    ${component}_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa,
+              Engines::Container_ptr container,
+              const char *instanceName, const char *interfaceName,
+              bool regist = true);
+    virtual ~${component}_i();
+${servicesdef}
+};
+
+extern "C"
+{
+    PortableServer::ObjectId * ${component}Engine_factory( CORBA::ORB_ptr orb,
+                                                      PortableServer::POA_ptr poa,
+                                                      PortableServer::ObjectId * contId,
+                                                      const char *instanceName,
+                                                      const char *interfaceName);
+}
+#endif
+
+"""
+hxxCompo=Template(hxxCompo)
+
+# Declaration of the thread function to run a MPI service.
+# template parameters:
+#   service : name of the service.
+#   input_vals : declarations of input ports of the service.
+hxxThreadService="""
+void * th_${service}(void * s);
+typedef struct {
+  int ip; // mpi process id
+  Engines::IORTab* tior;
+  ${input_vals}
+} thread_${service}_struct;
+
+"""
+hxxThreadService=Template(hxxThreadService)
+
+# Body of a service.
+# template parameters:
+#   module : module name
+#   component : component name
+#   service : service name
+#   out_vals : declaration of output ports ("type1 name1;\ntype2 name2;")
+#   service_call : 
+#   in_vals : copy of input ports to thread structure
+#   parameters : list of parameters ("type1 name1, type2 name2")
+#   body : user body
+cxxService="""
+void * th_${service}(void * s)
+{
+  std::ostringstream msg;
+  exception_st *est = new exception_st;
+  est->exception = false;
+  
+  thread_${service}_struct *st = (thread_${service}_struct *)s;
+  
+  try
+  {
+    ${out_vals}
+    ${module}_ORB::${component}_var compo = ${module}_ORB::${component}::_narrow((*(st->tior))[st->ip]);
+    compo->${service_call};
+  }
+  catch(const SALOME::SALOME_Exception &ex)
+  {
+    est->exception = true;
+    est->msg = ex.details.text;
+  }
+  catch(const CORBA::Exception &ex)
+  {
+    est->exception = true;
+    msg << "CORBA::Exception: " << ex;
+    est->msg = msg.str();
+  }
+  
+  delete st;
+  return ((void*)est);
+}
+
+void ${component}_i::${service}(${parameters})
+{
+  beginService("${component}_i::${service}");
+  void *ret_th;
+  pthread_t *th;
+  exception_st *est;
+
+  try
+    {
+      // Run the service in every MPI process
+      if(_numproc == 0)
+      {
+        th = new pthread_t[_nbproc];
+        for(int ip=1;ip<_nbproc;ip++)
+        {
+            thread_${service}_struct *st = new thread_${service}_struct;
+            st->ip = ip;
+            st->tior = _tior;
+            ${in_vals}
+            pthread_create(&(th[ip]),NULL,th_${service},(void*)st);
+        }
+      }
+      
+//BODY
+${body}
+//ENDBODY
+      if(_numproc == 0)
+      {
+        for(int ip=1;ip<_nbproc;ip++)
+        {
+          pthread_join(th[ip],&ret_th);
+          est = (exception_st*)ret_th;
+          if(est->exception)
+          {
+              std::ostringstream msg;
+              msg << "[" << ip << "] " << est->msg;
+              delete est;
+              delete[] th;
+              THROW_SALOME_CORBA_EXCEPTION(msg.str().c_str(),SALOME::INTERNAL_ERROR);
+          }
+          delete est;
+        }
+        delete[] th;
+      }
+    }
+  catch ( const SALOME_Exception & ex)
+    {
+      THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
+/*      SALOME::ExceptionStruct es;
+      es.text=CORBA::string_dup(ex.what());
+      es.type=SALOME::INTERNAL_ERROR;
+      throw SALOME::SALOME_Exception(es);*/
+    }
+  catch ( const SALOME::SALOME_Exception & ex)
+    {
+      throw;
+    }
+  catch ( const std::exception& ex)
+    {
+      THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
+/*      //std::cerr << typeid(ex).name() << std::endl;
+      SALOME::ExceptionStruct es;
+      es.text=CORBA::string_dup(ex.what());
+      es.type=SALOME::INTERNAL_ERROR;
+      throw SALOME::SALOME_Exception(es);*/
+    }
+  catch (...)
+    {
+      THROW_SALOME_CORBA_EXCEPTION("unknown exception", SALOME::INTERNAL_ERROR);
+/*      std::cerr << "unknown exception" << std::endl;
+      SALOME::ExceptionStruct es;
+      es.text=CORBA::string_dup(" unknown exception");
+      es.type=SALOME::INTERNAL_ERROR;
+      throw SALOME::SALOME_Exception(es);*/
+    }
+  endService("${component}_i::${service}");
+}
+
+"""
+cxxService=Template(cxxService)
+
+interface="""
+  interface ${component}:${inheritedinterface} Engines::MPIObject, Engines::EngineComponent
+  {
+${services}
+  };
+"""
+interface=Template(interface)
\ No newline at end of file
diff --git a/module_generator/mpicompo.py b/module_generator/mpicompo.py
new file mode 100644 (file)
index 0000000..21b20ad
--- /dev/null
@@ -0,0 +1,211 @@
+# Copyright (C) 2009-2015  EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+"""
+  Module that defines CPPComponent for SALOME components implemented in C++
+"""
+
+import os
+from gener import Component, Invalid
+from cpp_tmpl import initService, cxxService, hxxCompo, cxxCompo
+from cpp_tmpl import exeCPP, cmake_src_compo_cpp
+from yacstypes import corba_rtn_type, corba_in_type
+import mpi_tmpl
+from cppcompo import CPPComponent
+
+try:
+  from string import Template
+except:
+  from compat import Template,set
+
+class MPIComponent(CPPComponent):
+  """
+   A :class:`MPIComponent` instance represents a C++ SALOME component with services given as a list of :class:`Service`
+   instances with the parameter *services*.
+
+   :param name: gives the name of the component.
+   :type name: str
+   :param services: the list of services (:class:`Service`) of the component.
+   :param kind: If it is given and has the value "exe", the component will be built as a standalone
+      component (executable or shell script). The default is to build the component as a dynamic library.
+   :param libs: list of the additional libraries. see *Library* class.
+      If you want to add "libmylib.so", installed in "/path/to/lib" you should use:
+         libs=[Library(name="mylib", path="/path/to/lib")]
+      For more advanced features, see the documentation of cmake / FIND_LIBRARY
+   :param rlibs: space-separated list specifying the rpath to use in installed targets
+   :param includes: additional include directories, separated by spaces.
+   :param sources: gives all the external source files to add in the compilation step (list of paths).
+   :param exe_path: is only used when kind is "exe" and gives the path to the standalone component.
+   :param compodefs: can be used to add extra definition code in the component for example when using a base class
+      to define the component class by deriving it (see *inheritedclass* parameter)
+   :param inheritedclass: can be used to define a base class for the component. The base class can be defined in external
+      source or with the *compodefs* parameter. The value of the *inheritedclass* parameter is the name of the base class.
+   :param idls: can be used to add extra idl CORBA interfaces to the component. This parameter must gives a list of idl file
+      names that are added into the generated module (idl directory) and compiled with the generated idl of the module.
+   :param interfacedefs: can be used to add idl definitions (or includes of idl files) into the generated idl of the module.
+   :param inheritedinterface: can be used to make the component inherit an extra idl interface that has been included through
+      the *idls* and *interfacedefs* parameters. See the cppgui1 example for how to use these last parameters.
+   :param addedmethods: is a C++ specific parameter that can be used to redefine a component method (DumpPython for example). This
+      parameter is a string that must contain the definition and implementation code of the method. See the cppgui1 example
+      for how to use it.
+
+   For example, the following call defines a standalone component named "mycompo" with one service s1 (it must have been defined before)::
+
+      >>> c1 = module_generator.CPPComponent('mycompo', services=[s1,], kind="exe",
+                                             exe_path="./launch.sh")
+  """
+  def __init__(self, name, services=None, libs=[], rlibs="", includes="", kind="lib",
+                     exe_path=None, sources=None, inheritedclass="", compodefs="",
+                     idls=None,interfacedefs="",inheritedinterface="",addedmethods=""):
+    self.exe_path = exe_path
+    Component.__init__(self, name, services, impl="CPP", libs=libs, rlibs=rlibs,
+                             includes=includes, kind=kind, sources=sources,
+                             inheritedclass=inheritedclass, compodefs=compodefs, idls=idls,
+                             interfacedefs=interfacedefs, inheritedinterface=inheritedinterface,
+                             addedmethods=addedmethods)
+
+  def validate(self):
+    """ validate component definition parameters"""
+    Component.validate(self)
+    kinds = ("lib")
+    if self.kind not in kinds:
+      raise Invalid("kind must be one of %s for component %s" % (kinds,self.name))
+
+  def libraryName(self):
+    """ Name of the target library
+    """
+    ret=""
+    if self.kind == "lib":
+      ret = self.name + "Engine"
+    else:
+      raise Invalid("Invalid kind of component: %s. Supported kinds are 'lib' and 'exe'" % self.name)
+    return ret
+    
+  def makeCompo(self, gen):
+    """generate files for C++ component
+
+       return a dict where key is the file name and value is the file content
+    """
+    (cmake_text, cmake_vars) = self.additionalLibraries()
+    cmake_vars = "${KERNEL_SalomeMPIContainer}\n  " + cmake_vars
+    cxxfile = "%s.cxx" % self.name
+    hxxfile = "%s.hxx" % self.name
+    if self.kind == "exe":
+      exe_opt = 1
+    else:
+      exe_opt = 0
+    ret = { cxxfile:self.makecxx(gen, exe_opt),
+            hxxfile:self.makehxx(gen)
+          }
+    sources = " ".join(map(os.path.basename,self.sources))
+    cmakelist_content = cmake_src_compo_cpp.substitute(
+                        module = gen.module.name,
+                        component = self.name,
+                        componentlib = self.libraryName(),
+                        includes = self.includes,
+                        sources = sources,
+                        libs = cmake_vars,
+                        find_libs = cmake_text,
+                        target_properties = self.targetProperties())
+    
+    ret["CMakeLists.txt"] = cmakelist_content
+    
+    return ret
+
+  def makeThServiceDeclaration(self, service, module_name):
+    inputVals = []
+    for port in service.inport:
+      name, typ = service.validatePort(port)
+      inputVals.append("%s %s;" % (corba_in_type(typ, module_name), name ))
+    return mpi_tmpl.hxxThreadService.substitute(service=service.name,
+                                       input_vals="\n".join(inputVals))
+
+  def makehxx(self, gen):
+    """return a string that is the content of .hxx file
+    """
+    services = []
+    compodefs=self.compodefs
+    for serv in self.services:
+      service = "    %s %s(" % (corba_rtn_type(serv.ret,gen.module.name),serv.name)
+      service = service+gen.makeArgs(serv)+");"
+      services.append(service)
+      compodefs = compodefs + self.makeThServiceDeclaration(serv,gen.module.name)
+
+    if self.addedmethods:
+      services.append(self.addedmethods)
+    servicesdef = "\n".join(services)
+
+    inheritedclass=self.inheritedclass
+    if self.inheritedclass:
+      inheritedclass= " public virtual " + self.inheritedclass + ","
+
+    return mpi_tmpl.hxxCompo.substitute(component=self.name, module=gen.module.name,
+                               servicesdef=servicesdef, inheritedclass=inheritedclass,
+                               compodefs=compodefs)
+
+  def makecxx(self, gen, exe=0):
+    """return a string that is the content of .cxx file
+    """
+    services = []
+    inits = []
+    defs = []
+    for serv in self.services:
+      defs.append(serv.defs)
+      in_vals = []
+      out_vals = []
+      call_params = []
+      for name, typ in serv.inport:
+        in_vals.append("st->%s = %s;" % (name, name ))
+        call_params.append("st->%s" % name)
+        
+      for name, typ in serv.outport:
+        out_vals.append("%s %s;" % (corba_in_type(typ, gen.module.name), name ))
+        call_params.append(name)
+      
+      service_call = "%s(%s)" % (serv.name, ",".join(call_params))
+      
+      service = mpi_tmpl.cxxService.substitute(module=gen.module.name,
+                                      component=self.name, service=serv.name,
+                                      out_vals="\n".join(out_vals),
+                                      service_call=service_call,
+                                      in_vals="\n".join(in_vals),
+                                      parameters=gen.makeArgs(serv),
+                                      body=serv.body)
+      services.append(service)
+
+    return mpi_tmpl.cxxCompo.substitute(component=self.name,
+                               servicesdef="\n".join(defs),
+                               servicesimpl="\n".join(services))
+
+  def getIdlInterfaces(self):
+    services = self.getIdlServices()
+    inheritedinterface=""
+    if self.inheritedinterface:
+      inheritedinterface=self.inheritedinterface+","
+    return mpi_tmpl.interface.substitute(component=self.name,
+                                         services="\n".join(services),
+                                         inheritedinterface=inheritedinterface)
+
+  def getIdlDefs(self):
+    idldefs = """
+#include "SALOME_MPIObject.idl"
+"""
+    if self.interfacedefs:
+      idldefs = idldefs + self.interfacedefs
+    return idldefs
index 54cb20820b9cc4d3568fe5e1d922ff670a90f666..7ccdb785037de4caff4fad5a0936d7e2df67bea1 100644 (file)
@@ -32,6 +32,7 @@ from paco_tmpl import cxxFactoryDummy, cxxFactoryMpi, cxx_des_parallel_stream
 from paco_tmpl import hxxparallel_instream, hxxparallel_outstream, hxxinit_ok
 from paco_tmpl import hxxparallel_instream_init, hxxparallel_outstream_init, cxxService_connect
 from paco_tmpl import cxx_cons_service, cxx_cons_parallel_outstream, cxx_cons_parallel_instream
+from cata_tmpl import parallel_interface
 
 class PACOComponent(Component):
 
@@ -165,3 +166,29 @@ class PACOComponent(Component):
 
     return cxxfile
 
+  def getIdlServices(self):
+    services = []
+    for serv in self.services:
+      params = []
+      for name, typ in serv.inport:
+        if typ == "file":continue #files are not passed through IDL interface
+        params.append("in %s %s" % (idlTypes[typ], name))
+      for name, typ in serv.outport:
+        if typ == "file":continue #files are not passed through IDL interface
+        params.append("out %s %s" % (idlTypes[typ], name))
+      service = "    void %s(" % serv.name
+      service = service+",".join(params)+");"
+      services.append(service)
+    return services
+
+  def getIdlInterfaces(self):
+    services = self.getIdlServices()
+    return parallel_interface.substitute(component=self.name, services="\n".join(services))
+
+  def getIdlDefs(self):
+    idldefs = """
+#include "SALOME_PACOExtension.idl"
+"""
+    if self.interfacedefs:
+      idldefs = idldefs + self.interfacedefs
+    return idldefs