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.