Just a progress report. It's going well!

I have found ways to make more things work.

1. Move more C binding code to standard hpp file
======================================

The interface_file.flx now #include file.hpp, I have modified the
compiler so file.hpp is more suitable. This guarantees that any types
in the C code of the interface refer to the actual types Felix generated
for that file. In fact the C code part of the C binding code available
to the client is the identical file used when C++ compiling the library.

The code is NOT quite identical however because of a macro.
Exports are marked

        FLX_EXTERN_file

In the library, this is defined to FLX_EXPORT prior to #include.
In the interface, it's defined as FLX_IMPORT prior to #include.
Note that the current system leaves these both blank on Unix
systems, on Windows you get _dll_export and _dll_import for
dynamic linkage. However this will change because gcc and clang
both have visibility attributes now.

Just to remind you there are 3 levels of visibility:

        internal linkage (static function) -- visible in translation unit only
        external linkage (extern function) -- visible in static linkage only
        export linkage  -- visible in DLLs too

Older gcc/clang compilers only provided export linkage for extern.
This means every extern symbol in a fully linked shared library
was visible to clients of the library (eg for dlsym()).

These compilers now try to make it possible to do what Windows has 
always required: hide all symbols not marked for dynamic 
linkage visibility.

2. Support export struct
==================

Although not implemented I have tested this by hand. The idea is you can

        export struct X { x:int; };

in a library and the interface will say:

        cstruct X { x:int; };

This allows type X to be used as a structure, that is, it supports not only 
passing
values of that type, etc, but also construction and field access.

The cstruct construction mandates that the name of the underlying C structure 
is X.
exporting a type like

        export type (X) as "X";

will construct a typedef at global scope:

        typedef ::flxusr::file::X_mangled_name X;

which the C struct construction can then bind to.

3. By accident, list works
===================

For some reason I don't fully understand, a list is represented by a void*.
Since list of int, for example, is shared via the standard library,
lists can be passed back and forward across client/library boundaries.

It's not clear other union types will work, but possibly most they will because
the C representation is invariant. One case that will not work is the simplest:

        union X = C of Y;

Felix makes the representation just the representation of Y, so it's safe to 
use a uni-union .. i.e. a union with only one constructor .. without any 
performance loss. however other more complex unions are either standard
types that fix into a machine word, tagged pointers, of a _uctor_ data type
which is shared.

Just so you grok the issue again: Felix synthesises arbitrary indeterminate
C++ names for some structural types like tuples. For example the C++ type of

        int * double

in one compilation will not be the same struct in another. Of course the layout
will be the same.

This means that the interface for a function accepting a tuple argument
will have an argument of type generated when the library C++ code is
generated, which the client cannot know.

If we export this type:

        export type (int * double) as "intdouble";

what we get is:

        typedef ::flxusr::file::some_weird_mangled_name intdouble;

So now, we can use that type, but only as an abstract type!
If in our Felix client we try to pass

        (1, 2.3)

to the function, the C++ type will be:

        ::flxusr::client::some_other_weird_name

which is not the same type at all, and the C++ compiler will barf.
Indeed, although layout compatible the two versions of the tuple
are defined in both the client and library. But the exported abstract type
allows copying, but it will not allow field access. You would have to write
a cast (in Felix) to cast int * double to intdouble.

4. Exporting a cstruct?
=================

The "right" way to do share a C struct is a Felix include file which

(a) defines the cstruct and
(b) ensures the C definition is available

If you try to export a cstruct, then two interfaces exporting it
would get the same Felix name defined, causing an error.

Of course this would happen with a struct too. The difference is,
a struct *defines* a struct, and so should not be defined twice.
So when you export it the interface has a cstruct binding to it
which can be shared by including the interface. Include files
in Felix only get included once. Two distinct files defining the same
cstruct can be included twice.

There is an exception to this rule, where the cstruct in the library
is considered a defining specification. In that case the cstruct can
be exported into the interface, and is the sole binding used elsewhere.

Exporting a cstruct is tricky because the "requirements" that force the C 
definition
of the struct have to  be exported too.


--
john skaller
skal...@users.sourceforge.net
http://felix-lang.org




------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to