We will write the C++ implementation in the minimal/libCxx/ subdirectory of hello/. The first step is to run the Babel code generator on the SIDL file and have it generate the appropriate code. The simplified command to generate the Babel library code (assuming Babel is in your PATH) is 5.1:
% cd minimal/libCxx
% babel -sC++ -makefile ../../hello.sidl
In this Babel command, the ``-sC++'' flag, or its long form ``-server=C++'', indicates that we wish to generate C++ bindings for an implementation5.2. This command will generate a large number of C and C++ header and source files. It is often surprising to newcomers just how much code is generated by Babel. Rest assured, each file has a purpose and there is a lot of important things being done as efficiently as possible under the hood.
Files are named after the fully-qualified class-name. For instance, a package Hello and class World would have a fully qualified name (in SIDL) as Hello.World. This corresponds to file names beginning with Hello_World5.3. For each class, there will be files with _IOR, _Skel, or _Impl appended after the fully qualified name. Stubs often go without the _Stub suffix. IOR files are always in ANSI C (source and headers), containing Babel's Intermediate Object Representation. Impl files contain the actual implementation, and can be in any language that Babel supports, in this case, they're C++ files. Impl files are the only files that a developer need look at or touch after generating code from the SIDL source. Skel files perform translations between the IORs and the Impls. In some cases (like Fortran) the Skels are split into a few files: some in C, some in the Impl language. In the case of C++, the Skels are pure C++ code wrapped in extern "C" {} declarations. If the file is neither an IOR, Skel, nor Impl, then it is likely a Stub. Stubs are the proxy classes of Babel, performing translations between the caller language and the IOR. Finally, the file babel.make is a Makefile fragment that is used by GNUmakefile or to simplify making your own custom build. You may ignore the babel.make file if you wish. There are also babel.make.depends and babel.make.package files. These were added by external contributors, and we will ignore them in this document.
The only files that should be modified by the developer (that's you since you're implementing Hello World) are the ``Impls'', which are in this case files ending with _Impl.hxx or _Impl.cxx Babel generates these implementation files as a starting point for developers. These files will contain the implementation of the Hello library. Every implementation file contains many pairs of comment ``splicer'' lines such lines 4 and 6 in the following sample:
1 ::std::string 2 Hello::World_impl::getMsg_impl () 3 { 4 // DO-NOT-DELETE splicer.begin(Hello.World.getMsg) 5 // Insert-Code-Here {Hello.World.getMsg} (getMsg method) 6 // DO-NOT-DELETE splicer.end(Hello.World.getMsg) 7 }
Any modifications between these splicer lines will be saved after subsequent invocations of the Babel tool. Any changes outside the splicer lines will be lost. This splicer feature was developed to make it easy to do incremental development using Babel. By keeping your edits within the splicer blocks, you can add new methods to the hello.sidl file and rerun Babel without the loss of your previous method implementations. You shouldn't ever need to edit the file outside the splicer blocks.
For our hello application, the implementation is trivial. Add the following return statement between the splicer lines in the lib/Hello_World_Impl.cxx file:
::std::string Hello::World_impl::getMsg_impl () { // DO-NOT-DELETE splicer.begin(Hello.World.getMsg) return "Hello from C++!"; // DO-NOT-DELETE splicer.end(Hello.World.getMsg) }
The following is a listing of the generated GNUmakefile excluding the boilerplate copyright notice. It uses some of the tools installed along with Babel to automated generating a static and shared library provided that the machine supports both. The babel-config provides information about which compilers and compiler flags to use, and babel-libtool manages the building of object files and libraries.
1 include babel.make 2 # please name the server library here 3 LIBNAME=hello 4 # please name the SIDL file here 5 SIDLFILE=../../hello.sidl 6 # extra include/compile flags 7 EXTRAFLAGS= 8 # extra librarys that the implementation needs to link against 9 EXTRALIBS= 10 # library version number 11 VERSION=0.1.1 12 # PREFIX specifies the top of the installation directory 13 PREFIX=/usr/local 14 # the default installation installs the .la and .scl (if any) into the 15 # LIBDIR 16 LIBDIR=$(PREFIX)/lib 17 # the default installation installs the stub header and IOR header files 18 # in INCLDIR 19 INCLDIR=$(PREFIX)/include 20 21 # most of the rest of the file should not require editing 22 23 ifeq ($(IMPLSRCS),) 24 SCLFILE= 25 BABELFLAG=--client=cxx 26 MODFLAG= 27 else 28 SCLFILE=lib$(LIBNAME).scl 29 BABELFLAG=--server=cxx 30 MODFLAG=-module 31 endif 32 33 all : lib$(LIBNAME).la $(SCLFILE) 34 35 CC=`babel-config --query-var=CC` 36 CXX=`babel-config --query-var=CXX` 37 INCLUDES=`babel-config --includes-cxx` 38 CFLAGS=`babel-config --flags-c` 39 CXXFLAGS=`babel-config --flags-cxx` 40 LIBS=`babel-config --libs-cxx-client` 41 42 STUBOBJS=$(STUBSRCS:.cxx=.lo) 43 IOROBJS=$(IORSRCS:.c=.lo) 44 SKELOBJS=$(SKELSRCS:.cxx=.lo) 45 IMPLOBJS=$(IMPLSRCS:.cxx=.lo) 46 47 PUREBABELGEN=$(IORHDRS) $(IORSRCS) $(STUBSRCS) $(STUBHDRS) $(SKELSRCS) 48 BABELGEN=$(IMPLHDRS) $(IMPLSRCS) 49 50 $(IMPLOBJS) : $(STUBHDRS) $(IORHDRS) $(IMPLHDRS) 51 52 lib$(LIBNAME).la : $(STUBOBJS) $(IOROBJS) $(IMPLOBJS) $(SKELOBJS) 53 babel-libtool --mode=link --tag=CXX $(CXX) -o lib$(LIBNAME).la \ 54 -rpath $(LIBDIR) -release $(VERSION) \ 55 -no-undefined $(MODFLAG) \ 56 $(CXXFLAGS) $(EXTRAFLAGS) $^ $(LIBS) \ 57 $(EXTRALIBS) 58 59 $(PUREBABELGEN) $(BABELGEN) : babel-stamp 60 @if test -f $@; then \ 61 touch $@; \ 62 else \ 63 rm -f babel-stamp ; \ 64 $(MAKE) babel-stamp; \ 65 fi 66 67 babel-stamp: $(SIDLFILE) 68 @rm -f babel-temp 69 @touch babel-temp 70 babel $(BABELFLAG) $(SIDLFILE) 71 @mv -f babel-temp $@ 72 73 lib$(LIBNAME).scl : $(IORSRCS) 74 ifeq ($(IORSRCS),) 75 echo "lib$(LIBNAME).scl is not needed for client-side C bindings." 76 else 77 -rm -f $@ 78 echo '<?xml version="1.0" ?>' > $@ 79 echo '<scl>' >> $@ 80 if test `uname` = "Darwin"; then scope="global"; else scope="local"; \ 81 fi ; \ 82 echo ' <library uri="'`pwd`/lib$(LIBNAME).la'" scope="'"$$scope"'" resolution="lazy" >' >> $@ 83 grep __set_epv $^ /dev/null | awk 'BEGIN {FS=":"} { print $$1}' | sort -u | sed -e 's/_IOR.c//g' -e 's/_/./g' | awk ' { printf " <class name=\"%s\" desc=\"ior/impl\" />\n", $$1 }' >>$@ 84 echo " </library>" >>$@ 85 echo "</scl>" >>$@ 86 endif 87 88 .SUFFIXES: .lo .cxx .c 89 90 .c.lo: 91 babel-libtool --mode=compile --tag=CC $(CC) $(INCLUDES) $(CFLAGS) $(EXTRAFLAGS) -c -o $@ $< 92 93 .cxx.lo: 94 babel-libtool --mode=compile --tag=CXX $(CXX) $(INCLUDES) $(CXXFLAGS) $(EXTRAFLAGS) -c -o $@ $< 95 96 clean : 97 -rm -f $(PUREBABELGEN) babel-temp babel-stamp *.o *.lo 98 99 realclean : clean 100 -rm -f lib$(LIBNAME).la lib$(LIBNAME).scl 101 -rm -rf .libs 102 103 install : install-libs install-headers install-scl 104 105 106 install-libs : lib$(LIBNAME).la 107 -mkdir -p $(LIBDIR) 108 babel-libtool --mode=install install -c lib$(LIBNAME).la \ 109 $(LIBDIR)/lib$(LIBNAME).la 110 111 install-scl : $(SCLFILE) 112 ifneq ($(IORSRCS),) 113 -rm -f $(LIBDIR)/lib$(LIBNAME).scl 114 -mkdir -p $(LIBDIR) 115 echo '<?xml version="1.0" ?>' > $(LIBDIR)/lib$(LIBNAME).scl 116 echo '<scl>' >> $(LIBDIR)/lib$(LIBNAME).scl 117 if test `uname` = "Darwin"; then scope="global"; else scope="local"; \ 118 fi ; \ 119 echo ' <library uri="'$(LIBDIR)/lib$(LIBNAME).la'" scope="'"$$scope"'" resolution="lazy" >' >> $(LIBDIR)/lib$(LIBNAME).scl 120 grep __set_epv $^ /dev/null | awk 'BEGIN {FS=":"} { print $$1}' | sort -u | sed -e 's/_IOR.c//g' -e 's/_/./g' | awk ' { printf " <class name=\"%s\" desc=\"ior/impl\" />\n", $$1 }' >>$(LIBDIR)/lib$(LIBNAME).scl 121 echo " </library>" >>$(LIBDIR)/lib$(LIBNAME).scl 122 echo "</scl>" >>$(LIBDIR)/lib$(LIBNAME).scl 123 endif 124 125 install-headers : $(IORHDRS) $(STUBHDRS) 126 -mkdir -p $(INCLDIR) 127 for i in $^ ; do \ 128 babel-libtool --mode=install cp $$i $(INCLDIR)/$$i ; \ 129 done 130 131 .PHONY: all clean realclean install install-libs install-headers install-scl
The details of this makefile deserve careful explanation.
With the GNUmakefile in place we can simply go to that directory and build everything by typing make.