It was many times said in this thread that we need a language and 
compiler independent ABI for new API. It was also suggested to have 
machine-generated API descriptions for different languages. It was also 
mentioned that we need a better way to combine C++ exceptions with 
status vector when performing API calls than always manually adding 
try/catch and check for an error in status vector.

I want to suggest a first draft of [very restricted] IDL implementation 
for firebird that should solve all mentioned problems. As an additional 
non-mentioned before feature it solves the problem of making interface 
version upgrade compiler independent and reliable.

I do not use suggested here method of keeping interface in database and 
generating all needed from it. That's certainly simpler to generate but 
causes obvious problems at the boot stage of build. Therefore we should 
better use own IDL implementation to be able to generate interfaces' 
description from text files. I do not provide formal definition of 
language here - I hope that it's quite clear from the sample at 
http://web.firebirdsql.org/download/rabbits/alex/Interface.tgz . There 
are 4 files in it:
1. Interface.idl - description of our interfaces using IDL
2. Interface.h - c++ header (should be machine-generated from .idl, 
currently manually done)
3. implRefCounted.cpp - implementation of interface using that h-file
4. main.cpp - access to such interface

We can use very simplified IDL version cause we do not care about 
host2host transfers of calls (i.e. all FB interfaces are local). 
Replacing of remote subsystem is not a goal here. So description of 
interface becomes very simple:

interface IRefCounted : IVersioned
{
     addRef();
     int release();
};

where IRefCounted is it's name, IVersioned - name of base interface, and 
methods are provided after it in {} brackets. Any data types are 
accepted - we do not check for correctness (hmm, that may be a trouble 
when generating non-C++, but I hope it's solvable). I've also skipped 
'void' before fundtion returning nothing to make language look more 
pascal-friendly, but this is not critical detail.



What is generated from such description? I will not repeat here too much 
from Interface.h, just a plan of - what should be generated. Each 
interface is represented as c++ class with same name.

For primary (non having base) interface (IVersioned in our case) 
generated some generic macros and a pointer to virtual table as 'void* 
IDL_vt'.

The following is generated for all interfaces.

struct VTable - it's based on base interface's VTable. As typical 
virtual table it contains pointers to functions, representing interface 
methods. Due to inheritance it actually contains functions for current 
interface and all the chain of base interfaces.

Wrappers for calls in virtual table. I hope it's clear from the example 
what do they do, but I want to notice that calling that wrappers at c++ 
level is done in the exactly same way as is used currently in FB3. Also 
please take into an account that for methods, containing IStatus* as the 
first parameter, it's pretty easy to add check for an error after the 
call and throw an error in c++ style in machine-generated code therefore 
making actual code better.



This is the end of interface description, but in the end of generated 
file we have one more section which helps to implement interface. There 
are implementation header and footer, use of them is clear from 
implRefCounted.cpp file in the sample. Each implementation begins with 
static virtual table which will be assigned to IDL_vt of all instances. 
After it implementations of functions used in this vtable follow - they 
are certainly static and call appropriate function of user's interface 
implementation (will be extended with try/catch for methods with 
IStatus*). I.e. if there is 'addRef()' method in the interface user MUST 
implement 'void addRef()' function when implementing an interface. Or he 
gets compile-time error. Next function for vtable initialization follows 
- it must be called in any user's constructor.

In the footer of implementation there is a space for virtual table. And 
(pay attention) all this is under some simple #ifdefs. That ifdefs make 
implementation of interface very simple - one should define 
BEGIN_IMPLEMENT_IXXX macro as a name of implementation, next include 
generated h-file - and after it is free to write his own code to 
implement interface in traditional c++ way. In the end of interface 
implementation a trick use in the beginning is repeated with 
END_IMPLEMENT_IXXX macro. This is what is done in implRefCounted.cpp 
sample. Later access to such class has no specifics.

Use of such interfaces is even simpler - you may see in main.cpp that it 
absolutely does not differ from well known samples of interface usage.



As the result we get language-neutral compiler-independent ABI, with an 
ability to generate a kind of headers for any language, with a machine 
generated code to catch exceptions into status vector and raise them 
from it (if language supports certainly), with our own structure of 
virtual table and therefore absolutely stable and clear interface 
version upgrade and (as additional small bonus) we nned not count 
interface versions manually.

Estimated time required to code idl2h converter is not more than a week. 
That program is not needed for end-users - only for one who want to 
build firebird from sources and/or take part in the development. If we 
agree with such form of API description I volunteer to write the program.



------------------------------------------------------------------------------
Infragistics Professional
Build stunning WinForms apps today!
Reboot your WinForms applications with our WinForms controls. 
Build a bridge from your legacy apps to the future.
http://pubads.g.doubleclick.net/gampad/clk?id=153845071&iu=/4140/ostg.clktrk
Firebird-Devel mailing list, web interface at 
https://lists.sourceforge.net/lists/listinfo/firebird-devel

Reply via email to