Using the u3gl Program
The u3gl
program is a pre-linked executable that calls a specified
function in a specified shared library.
Linking a call-in executable can be a problem if you do not have a C++ compiler or if you do not have the correct version of the C runtime. Certain parts of Uniface are written in C++ and some platforms require that you can link these to the executable only if you use the same version of that C++ compiler. If you try this with a standard C compiler, you might get unresolved externals during linking because of the missing C++ run-time initialization.
For situations where buying the C++ compiler is a problem, Uniface introduces the
u3gl
program. The 3GL developer no longer needs to link an executable but only a
shared library (for which no C++ compiler is needed). The u3gl
program loads the
library and calls the entry point. Because u3gl
is distributed in executable
format, it is linked with the proper C++ compiler and so is able to do the C++ run-time
initialization on behalf of the shared library.
As an example, consider the simplest of call-in programs:
#include <h3gl.h> void main (int argc, char* argv[]) { (void)unifbeg(1); (void)urun((unsigned char *)argv[1], 0, 0, 0, 0); (void)unifend(-1); }
Assume this program is named callin.c and you are working on 32-bits Sun Solaris. Normally, you would compile and link this code into an executable call-in as follows:
$ cc -mt -I3gl/include -o callin callin.c -L./lib -lucall -lyrtl
If you wanted to run the form ENT, you would execute it from the command line as follows:
$ callin ent
If the linking fails with an unresolved C++ symbol, for example Unresolved symbol:
__shlinit (code)
, then it is time to use u3gl
.
u3gl
To put u3gl into action, first change your C code not to use
main
but some other entry point, for example, one named
callin
:
#include <h3gl.h> void callin (int argc, char* argv[]) { (void)unifbeg(1); (void)urun((unsigned char *)argv[1], 0, 0, 0, 0); (void)unifend(-1); }
Next, compile and link this code into a shared library callin.so rather than an executable callin:
$ cc -c -mt -KPIC -I3gl/include callin.c $ cc -G -z defs -mt -KPIC -o lib/libcallin.so -lc -L./lib -lucall -lurtl -lulib -lyrtl callin.o
Lastly, instead of running your executable, you run u3gl which in turn loads and executes your code, which will then run the form ENT:
$ bin/u3gl --shared=libcallin.so --func=callin ENT
Note that as with other examples, we created the shared library in the Uniface lib directory, to avoid having to change the LD_LIBRARY_PATH setting.
In the compile
command, you might notice a number of parameters we did
not have in the ‘normal’ case:
-z defs
Produce an error if not all symbols can be resolved at link time.
-KPIC
Produce position-independent code, which is a requirement for shared libraries on Solaris
-G
The output is to be a shared library rather than an executable.
To ensure that you detect any unresolved externals at link time, rather than at run time,
we recommend that you use the -z defs
flag (or equivalent) wherever possible. The
link commands given in Appendix Compile and link commands use these flags whenever one
is available for the platform.
The full syntax of the u3gl
program is as follows:
--shared=
SharedObjectNameThe default is
lib
ProgramnameStandardextension--func=
FunctionnameThe default is Programname
--help
This help
--usage
Gives information about why and how
--verbose
Verbose information
--
(Optional) start user's arguments
You can run u3gl
with the --help
switch to produce the
above information, or with the --usage
switch to produce elaborate help
information, including an example. The --verbose
switch is useful for
trouble-shooting in case the callin
does not function properly.
The --shared
and --func
switches are the essential ones.
With these, you specify the name of your shared library and the name of the entry point (function)
that should be called. The default values allow you to work without any parameters at all, so the
syntax can be the same as when you are working without using u3gl
.
If you create a copy or symbolic link of u3gl, and give it the name
callin
, you can leave out these parameters, because both will default to the
program name, in other words, the lib
prefix and the .so
suffix
for the shared library are not mandatory. Then you can once again simply say:
$ callin
without even having to know that it is implemented via u3gl.
Some more remarks to round off the discussion of u3gl:
- This functionality is available only on Unix and Linux platforms.
- As with normal Uniface applications, it is necessary to call insunis and to ensure that the LD_LIBRARY_PATH (or whatever it is called on your platform) is set correctly
- If your function has any command line parameters, such as the name of the form to run
in the above example, you can give these at the end of the command line, for example:
$ bin/u3gl --shared=libcallin.so --func=callin ENT
- If you have a command line parameter that starts with a double-dash
(
--
), you must tell u3gl that it is not a switch, but rather a parameter. You do this by adding a double-dash to signal the end of the switches and the start of the parameters, for example:$ bin/u3gl --shared=foo.so --func=bar -- --hello--