Introduction
If you are working with Uniface on Unix or Linux platforms, you might have encountered a specific challenge when creating call-in executables. Linking a call-in executable can become a headache if you do not have a C++ compiler, or worse, if you do not have the exact version of the C++ compiler used to build the Uniface runtime.
Uniface contains components written in C++. Consequently, some platforms require that you link your executables using the same C++ compiler version to handle runtime initialization correctly. Trying to do this with a standard C compiler often results in unresolved external errors, such as Unresolved symbol: __shlinit.
For scenarios where acquiring the specific C++ compiler is difficult or impossible, Uniface provides a utility called u3gl.
What is u3gl?
The u3gl program is a pre-linked executable provided by Uniface. It acts as a wrapper that loads a shared library (which you create) and calls a specified entry point function.
Because u3gl is already distributed as an executable linked with the correct C++ compiler, it handles the C++ runtime initialization on behalf of your shared library. This means you, as the 3GL developer, only need to link a shared library—executable linking is no longer required.
How to Implement u3gl
Here is a step-by-step guide on how to convert a standard call-in program to use u3gl.
1. Refactor the Entry Point
Consider a standard call-in program callin.c that uses main:
#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);
}
To use u3gl, rename the entry point from main to a custom function name, for example, callin:
#include <h3gl.h>
/* Changed from main to callin */
void callin (int argc, char* argv[])
{
(void)unifbeg(1);
(void)urun((unsigned char *)argv[1], 0, 0, 0, 0);
(void)unifend(-1);
}
2. Compile as a Shared Library
Instead of compiling an executable, you must compile and link the code into a shared library (e.g., callin.so).
Example commands (Solaris syntax):
$ 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
Key Flags used here:
-
-KPIC: Produces position-independent code (required for shared libraries on Solaris). -
-G: Instructs the linker to produce a shared library. -
-z defs: Produces an error if symbols cannot be resolved at link time (highly recommended to catch issues early).
3. Run with u3gl
Once the shared library is created (preferably in the Uniface lib directory to avoid LD_LIBRARY_PATH issues), you use u3gl to run it.
Syntax:
$ bin/u3gl --shared=libcallin.so --func=callin ENT
In this example, ENT is a form passed as an argument to the function.
Simplifying the Execution
The full syntax allows for customization via switches:
-
--shared=SharedObjectName: Defaults tolibProgramname.so -
--func=FunctionName: Defaults toProgramname -
--verbose: Useful for troubleshooting
Pro Tip: You can create a symbolic link or copy of u3gl and name it match your program (e.g., callin).
If you rename u3gl to callin, the utility automatically defaults the --shared and --func parameters to match the program name. You can then run it simply as:
$ callin
This runs the code without the user needing to know that u3gl is handling the execution in the background.
Important Considerations
- Platform Support: This functionality is available only on Unix and Linux platforms.
- Environment: As with standard Uniface applications, ensure
insunisis called andLD_LIBRARY_PATHis set correctly. -
Arguments: Command line parameters (like form names) are passed at the end of the command line. If a parameter starts with
--, use a double-dash separator:
bin/u3gl --shared=foo.so --func=bar -- --hello--
Top comments (0)