TechInfo # 5563
Short Description:
Using ESQL/C with a C++ Compiler
Long Description:
Original-From: johnl@informix.com (Jonathan Leffler)
Original-Date: Tuesday 12th December 1995
Updated-From: jleffler@informix.com (Jonathan Leffler)
Updated-Date: Tuesday 16th March 1999
Subject: Using ESQL/C with C++
One of the more common requests these days is:
How do I compile ESQL/C code for use with C++?
There have been a variety of answers, but not any one systematic answer.
Now there is what I believe is a workable answer -- it's all in the
attached shell archive.
What do you get?
* Updated ESQL/C prototypes for 4.00, 4.1x, 5.0x and 7.2x
* An esql++ compiler
* A pair of patch files for modifying your standard ESQL/C compiler.
Only use these if your ESQL/C is version 4.1 or 5.x; later versions
already have the necessary change).
* A minimal test application.
* No documentation apart from this message!
What do you need to do?
* Unpack the shell archive. For this discussion, it is assumed that you
do this in the directory /tmp/esql. Ideally, you need to have enough
permissions to copy files into $INFORMIXDIR, which means you should be
either informix or root. See below if this is not feasible.
* Place the esql* headers in either $INFORMIXDIR/incl (version 4)
or $INFORMIXDIR/incl/esql (version 5 or later)
* Place the esql++ script in $INFORMIXDIR/bin
* If you are using version 4.1x or 5.x ESQL/C, then do:
cd $INFORMIXDIR/bin; patch < /tmp/esql/patch.vN.esql
where you replace the N with either 4 or 5. If you don't have patch,
get it from the Internet. It is widely available. For example, it can
be tracked down via http://www.yahoo.com, following the Software link
(under Computers & Internet) and then GNU Software, or you can go
direct to ftp://prep.ai.mit.edu/pub/gnu (a heavily loaded system, so
use a mirror site if you can).
* Decide which version of ESQL/C you are using and set the ESQLC_VERSION
environment variable to a value such as:
export ESQLC_VERSION=506 # 5.06.UC1
If you do not do this, the esql++ script will run the esql script to
determine the correct version number for you each time it is run, but
it will be slower than setting the environment variable. Note that the
ClientSDK versions of ESQL/C have numbers like 916 (for ClientSDk
2.10). You should not try to use 730 as the version, even if you are
using ClientSDK 2.10 with IDS 7.30. It will probably work, but is
certainly not guaranteed to work. The automatic system uses the output
of 'esql -V', and so should you.
* Decide which C++ compiler you use -- if it isn't CC, either set:
export INFORMIXCPP=g++
or edit the esql++ script to make your C++ compiler into the default.
* Try compiling the test application:
make -f Makefile
* If your C++ compiler is ISO 14882:1998 compliant (eg EGCS 1.1.1) to the
extent of not recognizing the <iostream.h> header, compile the code
with CPP_FLAGS=-DISO14882_HEADERS; this will use <iostream> and <cstdlib> in
place of <iostream.h> and <stdlib.h>:
make -f Makefile CPP_FLAGS=-DISO14882_HEADERS
* Run it against your local stores database -- it should print a SELECT
statement and say that the tabid for the syscolumns table is 2.
What if you can't (or do not wish to) modify your INFORMIXDIR?
* If you need to patch the esql script (because you are using 4.1x or 5.x
ESQL/C), copy $INFORMIXDIR/bin/esql to somewhere where you can modify
it (eg /some/where/bin/esql). Remember that the directory needs to be
on your PATH and in front of the 'real' esql script which you cannot
modify. Then patch it as described above.
* Place the headers in another directory (eg /some/where/include).
* Modify esql++ so that:
-- arglist starts of with -I/some/where/include as one component
-- ESQL defaults to /some/where/bin/esql
* Copy the modified esql++ script into /some/where/bin.
* You may need to rehash your PATH, too, after doing these changes.
How should you use it after testing it?
* Any ESQL/C source file which also contains C++ statements should be
compiled with the esql++ compiler instead of the esql compiler.
* Any program which contains any C++ code should be linked with the
esql++ compiler instead of the esql compiler.
* Any ESQL/C source file which contains only C statements should still be
compiled with the esql compiler because the esql++ compiler always and
unconditionally compiles with the C++ compiler.
* Note that you can adjust the behaviour of the esql++ compiler with the
following environment variables:
ESQL
ESQLC_CPLUSPLUS_EXTENSION
ESQLC_RM_COMMAND
ESQLC_VERSION
INFORMIXC
INFORMIXCPP
TMPDIR
What about other versions of ESQL/C?
* If you are still using a pre-4.00 version of ESQL/C, the chances are
that the code which edits the 4.xx code will be useful. However, the
prototypes for the ESQL/C interface functions are not known and will
have to be determined by inspection of the generated code. Good luck!
It will probably be easier to upgrade to a later version.
* I haven't been able to test version 8.xx ESQL/C; it isn't available to
me. However, the indications are that it will need the same treatment
as the other post-5.00 implementations of ESQL/C.
* Testing with the version 9.10 ESQL/C compiler indicates that this
script is still necessary. See also the notes on version 7.24 below.
* Ideally, you won't need this script at all for post-9.xx versions. If
you are using some later version, you will need to revise the script so
that the case statement on $ESQLC_VERSION handles the new (presumably
4-digit) version number.
* Note that ESQL/C 7.24 has some support for C++ built in. In
particular, it preprocesses files with the .ecpp extension and then
compiles them with the C++ compiler. However, it is not very clever
about what it does; for example, it still includes the following stanza
in the generated output, which is an apalling idea for C++:
#if !defined(__STDC__)
#define const
#endif
On HP-UX 10.20, and probably on other machines too, the C++ compiler
does not define __STDC__ (which is probably correct as that define is
for ANSI C compilers, not C++ compilers). The 7.24 esql script does
not link the object code with the C++ compiler, which can also cause
problems. You can work around this by running the link command it with
INFORMIXC="C++ compiler" in the environment. Do not try to do this
when compiling traditional ESQL/C files to object code; they will be
compiled with the C++ compiler which will not, in general, work.
* ClientSDK 2.01 (which supplies ESQL/C 9.14) also does not work very
cleanly. For example, the -D options on the command line are not
relayed to the C++ compiler when the source is a .ecpp file, and the
linking is (still) done by the C compiler, which does not work in
general. C++ programs must be linked by the C++ compiler -- anything
else is to error-prone to be worth considering. One issue for the
design of the esql script is how to identify that the linker should be
the C++ compiler rather than the C compiler. When any C++ source is
passed to the script, this should be deducible by the script. Ideally,
there should be an argument to the esql script to specify each of the C
compiler, the C++ compiler, and the linker, and there should be an
option to specify that linking should be done by the C++ compiler
without specifying it as the linker. Note that you can specify the two
compilers only via the INFORMIXC and INFORMIXCPP environment variables;
there is no linker environment variable. Most of these observations
also apply to ESQL/C 7.24, but there are also the additional problems
shown in the previous bullet point.
* Note that in a pure C++ and ESQL/C program, you can get ClientSDK 2.01
to produce a program provided you set INFORMIXC and INFORMIXCPP to the
C++ compiler. However, if any of the code is pure C code (which cannot
be compiled by the C++ compiler), then this strategy for building the
program fails unless you compile the object files separately and then
link them with the standard esql script. For example, a prior version
of the test code did not use testc.c and testmain.ec included
<stdlib.h> and the main() function returned EXIT_SUCCESS directly.
When this code was modified so that the .ec files were renamed to .ecpp
files, the compilation succeeded when the command line was:
INFORMIXC="g++ -DESQLC_VERSION=914" \
INFORMIXCPP="g++ -DESQLC_VERSION=914" \
esql -o testapp testmain.ecpp testsub.ecpp testcpp.cc
However, this does not work in a single command with mixed C and C++
code as in the current version of the test. It will work if you
compile testc.c to object code with the C compiler before running the
following command:
INFORMIXC="g++ -DESQLC_VERSION=914" \
INFORMIXCPP="g++ -DESQLC_VERSION=914" \
esql -o testapp testmain.ecpp testsub.ecpp testcpp.cc testc.o
Obviously, you could compile the .ecpp and .cc files to object files
before doing the linking and the link will work if you name the object
files on the command line, but only if INFORMIXC points to the C++
compiler at link time. The compilation will not work if you do not
rename the .ec files to the convention expected by the ClientSDK 2.01
ESQL/C compiler.
* Since the above comments were written, the ESQL/C group stated in email
dated 1998-11-09 that the support was added but not tested, and will
neither be fixed nor documented. Obviously, the support should then be
removed, but inertia and past experience indicates that this will not
happen during the 20th Century (and might not happen during the 21st
either). Holding your breath waiting for this to be remedied is not
recommended.
Which versions of ESQL/C are are known to work with this?
* The code has been tested against Informix-ESQL/C versions 4.12.UC1,
5.08.UD1, 6.00.UE1, 7.13.UC1, 7.24.UC1, 9.12.UC2 on a Sun Sparc 20
running Solaris 2.5.1 with both SUNWspro C++ SPARCompiler SC4.0.1 and
GNU G++ 2.7.2.2 (circa December 1997)
* The code has also been tested against ESQL/C 7.24.UC1 and ClientSDK
2.01.UC1 on a Sun Sparc 20 running Solaris 2.6 with GNU G++ 2.8.1
(circa August 1998).
* The code has also been tested against ClientSDK 2.10.UC1 (ESQL/C
9.16.UC1), and with ClientSDK 2.20.UC1 (ESQL/C 9.20.UC1), on a Sun Sparc
20 running Solaris 2.6 with EGCS 1.1.1 (circa March 1999).
Are there any known bugs?
* Life will get very difficult if you pass arguments with quotes or
spaces in them to your compiler:
esql++ -DOPENQUOTE="'" -DSOMMAT="string with blanks" thingy.ec
I do have a solution: it is another program called escape which
deals with precisely that sort of problem.
arglist="$arglist `escape $arg`"
But that requires some more source and isn't generally necessary.
Also, the underlying esql script does not work reliably with such
arguments, so the changes needed are even more extensive than this
comment suggests.
* The esql7_20.h header is needed until bug B73951 is fixed.
* With ESQL/C versions prior to ClientSDK 2.01 (2.00 untested), the esql
script passed all the library options to the C and C++ compilers even
when generating object code and not an executable (indicated by the -c
option). With ClientSDK 2.01, this no longer occurs. This matters
because the GNU C and C++ compilers warn when the options are not used,
and it therefore makes for a very noisy compilation when the libraries
are passed to the compiler when linking to object code.
* Command line options such as -D, -ED, -I and -EI are not passed to the
compilers correctly.
Any problems? Better let me know. Especially if you've got a fix.
---------------------------------------------------------------------------
NB: This material is supplied 'as is' with no warranty of any kind. You
use it at your own risk. It is not officially supported by Informix
Software Inc.
---------------------------------------------------------------------------
Jonathan Leffler (jleffler@informix.com)
Informix Software Inc
@(#)$Id: README,v 1.12 1999/03/16 19:15:26 jleffler Exp $
: "@(#): shar.sh,v 2.1 1998/06/02 17:13:43 jleffler Exp $"