UNified Interfaces (UNI for short) is another attempt to make language independed Unified Interface Description Language. Goal of UNI project to have API description not depended on any type of languages like most of existent interface description languages.
Unified Interface is API description file which used for generation of actual header, include, unit, etc files for corresponding languages. UNI is much stricted in comparation of standard C/C++ header files. This means less errors and easy support. Pascal-like syntax as base is used with some modifications.
UNI files (.uni) can be converted to C/C++ header files (.h) using uni2h tool (see uni2h documentation for more details). For Pascal units uni2pas tool can be used. Fortran .fi and .fap files can be generated using uni2f. For REXX GCI uni2gci can be used. For generation of assembler include files (.inc) use uni2inc. Other tools can be created for different languages.
Idea of language neutral interface descriptions is not new. Exists lot of attempts to make such languages. One of most notable example is a Interface description language. Various OMG IDL dialects and extensions tries to be genreal purpose interface description language.
In general we have problems with real language construction and 'machine generated' bindings. Read article about this at http://www.acm.org/tsc/apis.html. We have real problem and have no actual solution for this. Human-writable code always will be better. So, main goal of UNI is to provide generic way to provide base API bindings for different languages. C/C++ headers not good solution for this because it is hard to automatically convert them to much stricted languages like Pascal, Ada, etc. Same problems with other 'generic' languages like IDL and its modifications. IDL files also hard to convert to languages with strict types.
So, UNI must be used for fast generation of 'generic' bindings with constructions less or more same in different languages. For more 'advanced' bindings human-writable bindings must be used. 'Advanced' bindings must use 'generic' bindings as underline code.
Again, UNI is not solution but good tool for produce and maintain actual API bindings for different languages.
Another problem is overhead constructions in real languages. If we need to describe function, for example, in C then we must 1) write function prototype 2) add to function prototype calling conversion (why? Whis is ABI specific) 3) link import library which will point to external dynamic library or link static library with function implementation 4) add #pragma's to modify some function calling aspects
So, some only API specific things (like function names, argument types and so on) mixed with ABI (calling conversion, function implementation place and so on). UNI describes only API. For ABI description we use ABI. So we have clean division of API and ABI. This is also make maintaince easy.
Alphabet of UNI consist of latin alpha characters (a-z and A-Z), digits (0-9) and special chars (;:=,_^.).
Identifiers used to name functions, types, constants and so on. Identifier can use chars [a-zA-Z_]. [_] can not be used as first char.
Global language construction is a interfaces group. Interfaces group can contain types and constants definitions and interfaces description.
group <groupname>; <interfaces descriptions> end.
Example:
group dostime; constant DEMO=15; function DosGetTime(out msec: ULONG): APIRET; end.
Constant used to define constant values.
constant <constantname>=<constantvalue>;
Example:
constant DEMO=123;
Type used for new types definition. UNI support base types which can be used for new types construction.
type <typename>=<typedef>;
TODO base types not formulated yet
Draft begin
Draft end
Procedure is one of eases interface type. It is just only one call interface.
procedure <procedurename(<arguments>);
Example:
procedure DosSetTime(in time: TTIME);
Function is one of easest interface type. It is just only one call interface.
function <procedurename(<arguments>): <resulttype>;
Example:
function DosSetTime(in time: TTIME): APIRET;
Interface is a generic interface description mainly used for represent classes, messages/events, procedure calls.
interface <interfacename>; <methods> end;
Example:
interface window; function create(): APIRET; function paint(): APIRET; end;
Sometimes iterface group includes one or more other interface groups. For example, OS/2 Pesronality API sub.uni includes kbd.uni, mou.uni and vio.uni. UNI allow you to include such interface groups. For example:
group sub; includes kbd; includes mou; includes vio; end.
This mean: if you use sub group then kbd, mou and vio groups also will be included. So you can (for example in C) just include sub.h and kbd.h, mou.h and vio.h will be included automatically.
Somtimes we need control includion process (such approach used in preprocessor based toolchain, like C). For example, we need include interface goup only if defined preprocessor directive and not include otherwise. For such optional includions optional keyword is used. For example:
group sub;
includes vio optional; includes kbd; includes mou;
end;
In such case vio.h will be included only if preprocessor defines INCL_VIO symbol.
For modular languages (like Pascal) optional keyword say to ignore this interface group because preprocessor defined in parent module directives doesn't work in child modules.
Note: Don't use includes for symbol dependences resolving. Anothe mechanizm used for this issue
Keyword requires used to resolve symbol dependendences. In preprocessor based toolchains include preprocessor directive used for such issues, but in module-based toolchains special keywords are used.
| Unified | C/C++ | Pascal |
|---|---|---|
| requires | #include | uses |
| includes | #include | $I |
| includes optional | #ifdef INCL_xxx #include xxx #endif | - |