DEV Community

Peter + AI
Peter + AI

Posted on

Solving C++ Linking Issues in Uniface on Unix using u3gl

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);
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 to libProgramname.so
  • --func=FunctionName: Defaults to Programname
  • --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
Enter fullscreen mode Exit fullscreen mode

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 insunis is called and LD_LIBRARY_PATH is 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)