Introduction
If you work with Uniface, you know it’s a powerful low-code platform for building enterprise applications. However, there are moments when standard 4GL isn't enough. You might need high-performance algorithms, specific system calls, or integration with existing libraries. This is where the 3GL (Third-Generation Language) interface comes into play.
In this post, I’ll break down how Uniface handles 3GL integration, which languages work best, and the constraints you need to know.
The Core Concept: It’s All About the "C" Connection
Strictly speaking, Uniface isn't tied to a single specific 3GL language. However, because the Uniface kernel itself is largely written in C, the interface is heavily biased toward C conventions.
For a language to be compatible with Uniface, it must meet three critical conditions:
- Calling Convention: It must use the C calling convention for parameter passing.
- Relocatable Objects: The compiler must generate relocatable object modules.
- Shared Libraries: You must be able to link these modules into a shared library (DLL on Windows, .so on Linux/Unix).
Supported Languages (and the "Gotchas")
Because of the rules above, not every modern language is a plug-and-play fit.
✅ The Good Candidates:
- C / C++: The native choice. Uniface header files are written for C, and data types align perfectly.
- Pascal, Fortran, Ada: Possible, provided they meet the linking requirements.
- Visual Basic (Classic): Can work if it creates standard DLLs.
❌ The Difficult Ones:
- Java & .NET (C#): These usually run on managed runtimes (JVM/CLR). Unless you commit to unmanaged code or COM bridging, they don't fit the "shared library" requirement directly in this context.
- Interpreted COBOL: If your COBOL compiler generates intermediate code for a runtime interpreter, it won't work. You need a COBOL compiler that outputs object code linkable into a shared library.
Why C is the "Happy Path"
While you can use other languages, C is the path of least resistance. Here is why:
- Data Types: Uniface expects C-style data types.
- Strings: Uniface relies on zero-terminated strings (null-terminated), a standard in C.
- Headers: The provided include files from Uniface are specific to C.
Handling Non-C Languages: The Wrapper Strategy
If you need to call complex C++ code or another language that doesn't perfectly align with C conventions (for example, due to Name Mangling in C++), don't try to force it directly.
The Best Practice: Write a small C Wrapper.
The wrapper acts as a translator. It exposes a clean, C-compatible interface to Uniface while handling the specific idiosyncrasies (like object instantiation or mangled names) of your target language behind the scenes.
Example Scenario
Imagine you have a C++ library that performs a complex calculation.
1. The C++ Class (The "Real" Logic):
// calculator.cpp
class ComplexCalculator {
public:
int performMagic(int input) {
return input * 42; // Imagine complex logic here
}
};
2. The C Wrapper (The Bridge):
This is what Uniface will actually call. It uses extern "C" to prevent name mangling.
// wrapper.cpp
extern "C" {
#include "h3gl.h" // Standard Uniface header
long call_calculator(long input) {
ComplexCalculator calc;
return (long)calc.performMagic((int)input);
}
}
Typical Problems & Solutions
When integrating 3GL, here are common issues developers face:
Memory Leaks:
Problem: If your 3GL code allocates memory (malloc/new) and expects Uniface to free it, or vice versa, you will run into trouble.
Solution: Always manage memory ownership clearly. If the 3GL routine allocates it, provide a 3GL routine to free it.
String Termination:
Problem: Uniface sends a string, but your Fortran or Pascal routine doesn't expect a null terminator \0 and reads garbage memory.
Solution: Use the C wrapper to convert Uniface strings to the format your target language expects before passing them on.
Architecture Mismatch:
Problem: Trying to load a 32-bit DLL into a 64-bit Uniface runtime (or vice versa).
Solution: Ensure your shared libraries are compiled for the exact same architecture as your Uniface executable.
Conclusion
Integrating 3GL into Uniface opens up a world of possibilities for performance optimization and system integration. While you have theoretical freedom in language choice, sticking to C or using C-wrappers for C++ is the most robust workflow.
Have you worked with 3GL in Uniface? Let me know in the comments if you prefer direct C calls or if you’ve managed to bridge other languages!
Sources & References
Top comments (0)