[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Interfacing to C (was: OOC Core Library)



On Dec 6 Michael van Acken wrote:

> >  I'm in favour of a portable syntax for specifying external linkage
> >  specifiers (["C"]) and external identifiers (["sprintf"] etc).
> >  External libraries are a bit difficult to specify portable (they aren't
> >  called the same at each system, eg on RISC OS the shared C library is
> >  called stubs instead of libc).
>
> Portability of system dependent modules.  Somewhat paradox, isn't it.

Portability is out of the question. There are three C compilers for the
Amiga, and it's not possible to create a single interface that would work
with all three, even for the core ANSI C libraries. One (GNU) doesn't even
produce standard AmigaOS object files.

> But I agree that the back-end people should agree on notation that is
> shared by all back-ends, but may have extensions to serve the need of
> the particular back-end and its underlying OS.

For what its worth, the notation I used for Oberon-A is based on a numeric
code for each set of conventions I chose to implement:

  1 = Modula-2
  2 = C
  3 = BCPL
  4 = Assembler

I also defined

  0 = Oberon

for cases where I wanted to be able to override the module-wide default set
in the module header.

> Interfacing to a language that doesn't share Oberon-2 type rules and
> calling conventions has some other problems.	Take for example C:
> * structs
> are not identical to O2 RECORDS, because they
>   can't be extended,
>   they can't extend another type,

There's no reason why C structs can't be made extensible. In Oberon-A they
are, and its quite handy for cutting down the number of explicit type casts
required. The AmigaOS is actually quite object-oriented in design, and type
extension is simulated by 'sub-classing'. This means an object of the
parent type is included in the derived type as the first field. For
example:

    struct Node {
	...
    };

    struct Message {
	struct	Node mn_Node;
	...
    };

This could be defined in Oberon as:

    Node = RECORD [2]
      ...
    END;

    Message = RECORD [2] (Node)
      ...
    END;

This is most convenient when passing pointers as procedure parameters,
where the Oberon assignment compatibility rules can be applied instead of
having a lot of messy type-casts.

> * unions
> no counterpart in O2

I toyed with adding a union construct to Oberon-A, but thankfully they are
quite rarely used in AmigaOS and I decided to leave them out. Type-casts
and alternative type declarations can be used in the few cases where it
matters.

> My idea to solve this problem is to map (syntactically) each foreign
> type, variable, parameter, and procedure on the O2 syntax (eg, C
> struct becomes O2 RECORD) and give them additional flags that signal
> how they differ from the standard O2 stuff.  For example the C struct
> would have the flags "can't extend", "can't be extended", "no type
> descriptor" or "untagged" set.  The front-end knows those flags and
> how they influence semantic checks (and--possibly--GSA code
> generation).	It would prevent any attempts to extend this type or to
> apply a type test to it, but otherwise treat it just like any other O2
> type.

This is basically how Oberon-A deals with foreign constructs.

> I'm not that happy with it either.  But there may be a situation where
> someone has to use variable argument lists in order to interface to
> the very specific and elaborate C based library he needs for his
> project.  I wouldn't like to tell this person that it isn't possible...
> Anyway, var args are already part of the front-end, although I haven't
> tested it lately.  So it's up to you if you want to allow var arg
> declaration in interfaces to foreign languages or not.

Variable argument lists are pretty well a necessity for interfacing to
AmigaOS. It makes wide use of 'tag lists' to implement a very flexible
parameter-passing convention. Instead of having long fixed parameter lists,
functions get their parameters as key/value pairs which are interpreted in
whichever way makes most sense for the function. While these can be
simulated with open arrays, variable argument lists are syntactically much
more convenient for the programmer and it would be difficult to persuade
people to do without them.

Frank