cxx_svc_impl.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- python -*-
00003 #
00004 #  @file cxx_svc_impl.py
00005 #  @brief rtc-template C++ service source code generator class
00006 #  @date $Date: 2007-02-07 02:51:49 $
00007 #  @author Noriaki Ando <n-ando@aist.go.jp>
00008 # 
00009 #  Copyright (C) 2005-2007
00010 #      Task-intelligence Research Group,
00011 #      Intelligent Systems Research Institute,
00012 #      National Institute of
00013 #          Advanced Industrial Science and Technology (AIST), Japan
00014 #      All rights reserved.
00015 # 
00016 #  $Id: cxx_svc_impl.py 775 2008-07-28 16:14:45Z n-ando $
00017 # 
00018 
00019 import string
00020 import os
00021 
00022 # omniidl modules
00023 import _omniidl
00024 from omniidl import idlast, idlvisitor
00025 from omniidl_be.cxx import ast, util, id, types, output
00026 
00027 # import myself
00028 import cxx_svc_impl
00029 self = cxx_svc_impl
00030 
00031 
00032 #------------------------------------------------------------
00033 # Example code
00034 #------------------------------------------------------------
00035 interface_def = """\
00036 /*
00037  * Example class implementing IDL interface @fq_name@
00038  */
00039 class @impl_fqname@
00040  : public virtual @fq_POA_name@,
00041    public virtual PortableServer::RefCountServantBase
00042 {
00043  private:
00044    // Make sure all instances are built on the heap by making the
00045    // destructor non-public
00046    //virtual ~@impl_name@();
00047 
00048  public:
00049    // standard constructor
00050    @impl_name@();
00051    virtual ~@impl_name@();
00052 
00053    // attributes and operations
00054    @operations@
00055 };
00056 """
00057 
00058 interface_code = """\
00059 /*
00060  * Example implementational code for IDL interface @fqname@
00061  */
00062 @impl_fqname@::@impl_name@()
00063 {
00064   // Please add extra constructor code here.
00065 }
00066 
00067 
00068 @impl_fqname@::~@impl_name@()
00069 {
00070   // Please add extra destructor code here.
00071 }
00072 
00073 
00074 /*
00075  * Methods corresponding to IDL attributes and operations
00076  */
00077 @operations@
00078 
00079 // End of example implementational code
00080 """
00081 
00082 class_h = """\
00083 // -*-C++-*-
00084 /*!
00085  * @atmark@file  @impl_h@
00086  * @atmark@brief Service implementation header of @file@
00087  *
00088  */
00089 
00090 #include "@skel_h@"
00091 
00092 
00093 #ifndef @include_guard@
00094 #define @include_guard@
00095  
00096 @interfaces@
00097 
00098 #endif // @include_guard@
00099 
00100 """
00101 
00102 class_cpp = """\
00103 // -*-C++-*-
00104 /*!
00105  * @atmark@file  @impl_cpp@
00106  * @atmark@brief Service implementation code of @file@
00107  *
00108  */
00109 
00110 #include "@impl_h@"
00111 
00112 @interfaces@
00113 """
00114 
00115 def generate(idl_file, preproc_args, impl_suffix, skel_suffix = "Skel", fd_h=None, fd_cpp=None):
00116         basename = idl_file.replace(".idl","")
00117         preprocessor_cmd = "omnicpp"
00118         preprocessor_opt = "-I" + string.join(preproc_args, " -I")
00119 
00120         preproc_cmd = '%s %s %s' % (preprocessor_cmd,\
00121                                   preprocessor_opt, idl_file)
00122 
00123         file = os.popen(preproc_cmd, "r")
00124 
00125         skel_filename = basename + skel_suffix + ".h"
00126         idl_filename = idl_file
00127 
00128         # ignore the following operations
00129         ignore_operations = ["profile"]
00130         
00131         tree = _omniidl.compile(file)
00132         ast.__init__(tree)
00133 
00134         cxx_svc_impl.__init__(idl_filename, \
00135                                           basename, \
00136                                           skel_filename, \
00137                                           impl_suffix, \
00138                                           ignore_operations, \
00139                                           fd_h, \
00140                                           fd_cpp)
00141         ifs = cxx_svc_impl.run(tree)
00142         file.close()
00143         _omniidl.clear()
00144         return ifs
00145 
00146 
00147 #============================================================
00148 # This module's __init__()
00149 #============================================================
00150 def __init__(idl_filename, impl_basename, skel_filename, \
00151                 suffix = "_impl", ignore_op = [], fd_h = None, fd_cpp = None):
00152         self.idl_filename = idl_filename
00153         self.suffix = suffix
00154         self.impl_h_filename = impl_basename + self.suffix + ".h"
00155         self.impl_cpp_filename = impl_basename + self.suffix + ".cpp"
00156         self.skel_filename = skel_filename
00157         self.ignore_op = ignore_op
00158 
00159         self.include_guard = self.impl_h_filename.upper().replace(".","_")
00160 
00161         if fd_h == None:
00162                 self.stream_h = \
00163                     output.Stream(output.createFile(self.impl_h_filename), 2)
00164         else:
00165                 self.stream_h = output.Stream(fd_h, 2)
00166                 
00167         if fd_cpp == None:
00168                 self.stream_cpp = \
00169                     output.Stream(output.createFile(self.impl_cpp_filename), 2)
00170         else:
00171                 self.stream_cpp = output.Stream(fd_cpp, 2)
00172                 
00173         
00174 
00175 # Given an IDL name convert it into the fully qualified name of the
00176 # implementation class
00177 def impl_fullname(name):
00178     bits = name.suffix(self.suffix).fullName()
00179     return string.join(bits, "_")
00180 
00181 # Convert an IDL name into the simple name of the implementation class
00182 def impl_simplename(name):
00183     return impl_fullname(name)
00184 
00185 #
00186 # Main code entrypoint
00187 #
00188 def run(tree):
00189         # The implementation template code stream
00190         impl_cpp = output.StringStream()
00191         # The implementation template header stream
00192         impl_h   = output.StringStream()
00193         bii = BuildInterfaceImplementations(impl_h, impl_cpp, self.ignore_op)
00194         tree.accept(bii)
00195 
00196         # Generate mplementation class template header
00197         stream_h.out(class_h,
00198                                  atmark = "@",
00199                                  impl_h = self.impl_h_filename,
00200                                  include_guard = self.include_guard,
00201                                  skel_h = self.skel_filename,
00202                                  file = self.idl_filename,
00203                                  interfaces = str(impl_h))
00204         
00205         # Generate implementation class template code
00206         stream_cpp.out(class_cpp,
00207                                    atmark = "@",
00208                                    impl_cpp = self.impl_cpp_filename,
00209                                    impl_h = self.impl_h_filename,
00210                                    file = self.idl_filename,
00211                                    interfaces = str(impl_cpp))
00212 
00213         self.ifs = []
00214         for n in bii.allInterfaces():
00215                 self.ifs.append(string.join(n.scopedName(), "_") + self.suffix)
00216         return self.ifs
00217         
00218         
00219 
00220 
00221 #============================================================
00222 # Build the interface implementations
00223 #============================================================
00224 class BuildInterfaceImplementations(idlvisitor.AstVisitor):
00225 
00226         def __init__(self, stream_h, stream_cpp, ignore_operations):
00227                 self.stream_h = stream_h
00228                 self.stream_cpp = stream_cpp
00229                 self.ignore_operations = ignore_operations
00230                 # keep track of all interfaces for later use
00231                 self.__allInterfaces = []
00232 
00233         # Returns the list of all present interfaces (each one will be
00234         # implemented)
00235         def allInterfaces(self):
00236                 return self.__allInterfaces[:]
00237 
00238         # Tree walking code
00239         def visitAST(self, node):
00240                 for n in node.declarations():
00241                         if ast.shouldGenerateCodeForDecl(n):
00242                                 n.accept(self)
00243 
00244         # modules can contain interfaces
00245         def visitModule(self, node):
00246                 for n in node.definitions():
00247                         n.accept(self)
00248 
00249         # interfaces cannot be further nested
00250         def visitInterface(self, node):
00251                 self.__allInterfaces.append(node)
00252         
00253                 scopedName = id.Name(node.scopedName())
00254                 
00255                 cxx_fqname = scopedName.fullyQualify()
00256                 impl_flat_name = impl_fullname(scopedName)
00257 
00258                 fqname = scopedName.fullyQualify(cxx = 0)
00259 
00260                 
00261                 # build methods corresponding to attributes, operations etc.
00262                 # attributes[] and operations[] will contain lists of function
00263                 # signatures eg
00264                 #   [ char *echoString(const char *mesg) ]
00265                 attributes = []
00266                 operations = []
00267                 virtual_operations = []
00268 
00269                 # we need to consider all callables, including inherited ones
00270                 # since this implementation class is not inheriting from anywhere
00271                 # other than the IDL skeleton
00272                 allInterfaces = [node] + ast.allInherits(node)
00273                 allCallables = util.fold( map(lambda x:x.callables(), allInterfaces),
00274                                                                   [], lambda x, y: x + y )
00275 
00276 
00277                 # declarations[] contains a list of in-class decl signatures
00278                 # implementations[] contains a list of out of line impl signatures
00279                 # (typically differ by classname::)
00280                 declarations = []
00281                 implementations = []
00282                 
00283                 for c in allCallables:
00284 
00285                         if isinstance(c, idlast.Attribute) :
00286                                 attrType = types.Type(c.attrType())
00287                                 d_attrType = attrType.deref()
00288 
00289                                 for i in c.identifiers():
00290                                         attribname = id.mapID(i)
00291                                         returnType = attrType.op(types.RET)
00292                                         inType = attrType.op(types.IN)
00293                                         attributes.append(returnType + " " + attribname + "()")
00294                                         # need a set method if not a readonly attribute
00295                                         if not c.readonly():
00296                                                 args = attribname + "(" + inType + ")"
00297                                                 declarations.append("void " + args)
00298                                                 implementations.append("void " + impl_flat_name +\
00299                                                                                            "::" + args)
00300                                         if not attribname in self.ignore_operations:
00301                                                 declarations.append(returnType + " " + attribname + "()")
00302                                                 implementations.append(returnType + " " + impl_flat_name+\
00303                                                                                    "::" + attribname + "()")
00304                         elif isinstance(c, idlast.Operation):
00305                                 params = []
00306                                 for p in c.parameters():
00307                                         paramType = types.Type(p.paramType())
00308                                         cxx_type = paramType.op(types.direction(p), use_out = 0)
00309                                         
00310                                         argname = id.mapID(p.identifier())
00311                                         params.append(cxx_type + " " + argname)
00312 
00313                                 # deal with possible "context"
00314                                 if c.contexts() != []:
00315                                         params.append("CORBA::Context_ptr _ctxt")
00316 
00317                                 return_type = types.Type(c.returnType()).op(types.RET)
00318 
00319                                 opname = id.mapID(c.identifier())
00320                                 if not opname in self.ignore_operations:
00321                                         arguments = string.join(params, ", ")
00322                                         args = opname + "(" + arguments + ")"
00323                                         declarations.append(return_type + " " + args)
00324                                         implementations.append(return_type + " " + \
00325                                                                                    impl_flat_name + \
00326                                                                                    "::" + args)
00327                         else:
00328                                 util.fatalError("Internal error generating interface member")
00329                                 raise "No code for interface member: " + repr(c)
00330 
00331                 # the class definition has no actual code...
00332                 defs = string.join(map(lambda x:x + ";\n", declarations), "")
00333 
00334                 # Output the class definition of the implementation
00335                 self.stream_h.out(interface_def,
00336                                                   impl_fqname = impl_flat_name,
00337                                                   impl_name = impl_flat_name,
00338                                                   fq_name = fqname,
00339                                                   fq_POA_name = "POA_" + cxx_fqname,
00340                                                   operations = defs)
00341 
00342                 # Output the class methods implementations
00343                 impls = string.join(map(lambda x: x + """\
00344 
00345 {
00346   // Please insert your code here and remove the following warning pragma
00347 #ifndef WIN32
00348   #warning "Code missing in function <""" + x + """>"
00349 #endif
00350 }
00351 
00352 """,
00353                                                                 implementations), "")
00354                 
00355                 self.stream_cpp.out(interface_code,
00356                                                         fqname = fqname,
00357                                                         impl_name = impl_flat_name,
00358                                                         impl_fqname = impl_flat_name,
00359                                                         operations = impls)
00360 
00361 
00362 if __name__ == "__main__":
00363         import cxx_svc_impl
00364         import sys
00365         print "Interfaces:"
00366         print cxx_svc_impl.generate(sys.argv[1], "SVC_impl")


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Thu Aug 27 2015 14:16:37