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
[email protected]
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language