External types
There are currently two competing mechanisms. Their expressivity is roughly the same (when you have one it is easy to emulate the other).
For syntactic experiments, we'll assume the following C files are used but the syntax will have to be flexible enough to work for other external languages (e.g. Java).
my_struct.h:
typedef struct { double x; int c; } my_struct;
my_struct.c:
#include "my_struct.h" use (my_struct *x) { x->x = 3.14; if(x->c == 0) x->c = 5; else x->c++; printf("x = %f, c = %d\n", x->x, x->c); }
The program should print
x = 3.14, c = 5 x = 3.14, c = 6
External attributes
A special marker is used to tell the Eiffel compiler that an attribute should be represented by a user-specified external type. The only meaningful thing that can be done with it is passing it as a parameter to external routines.
Issues:
- what is the Eiffel type of the attribute?
- when "passing" the attribute, do we pass a copy or a reference?
Two suggested versions
Faux procedures
class SHOW creation make feature make is do use($ext) use($ext) end use(x: POINTER) is external "plug_in" alias "{ location: "./" module_name: "struct" feature_name: "use" }" end ext is external "plug_in" alias "{ location: "./" module_name: "struct" attribute_type: "my_struct" }" end end
Faux pointers
class SHOW creation make feature make is do use(ext) use(ext) end use(x: POINTER) is external "plug_in" alias "{ location: "./" module_name: "struct" feature_name: "use" }" end ext: POINTER is external "plug_in" alias "{ location: "./" module_name: "struct" attribute_type: "my_struct" }" end end
External classes
A special marker is used to tell the Eiffel compile that a class should be represented by a user-specified external type. Methods of that class can be implemented by passing Current as a parameter to external routines. Whether Current is passed by copy or by reference could be determined by the reference/expanded status of the external class.
Issues:
- Forces the programmer to write one class for each external type they want to wrap
- It wouldn't be possible to inherit from/insert that kind of class
- such classes should not inherit/insert other classes (ANY?)
- Implementing some of ANY's operations for external types might be difficult
- How are native eiffel attributes in such a class handled?
- Forbid them is not nice, since this may yield to to need to write two classes in special cases, also this would be a special case, which is not nice in general.
- Allowing, would force a dedicated ordering in the generated struct for the eiffel object
expanded class SHOW external "plug_in" alias "{ location: "./" module_name: "struct" attribute_type: "my_struct" }" creation make feature make is do -- Memory is zeroed, so we probably don't need to initialize x and -- c. If we do, we'll have to call a C function to do it. use($Current) use($Current) end use(x: POINTER) is external "plug_in" alias "{ location: "./" module_name: "struct" feature_name: "use" }" end end
Inline external classes
Ok, so there are actually three mechanisms, but this one is hybrid between the previous two (give the external attribute an Eiffel type that doesn't need to be defined anywhere else)
With this approach we can even allow this type for external features, which would solve the pass-by-value/reference question: do a copy or use a pointer to it.
Issues:
- What is the scope of such a type? Only visible in the class it is written in? Are two external types with the same "name" in different classes the same?
- What is the use of the type name? I'd just ommit it (ext: external is ...) --Cyril 15:12, 18 Jul 2007 (CEST)
class SHOW creation make feature make is do use($ext) use($ext) end use(x: POINTER) is external "plug_in" alias "{ location: "./" module_name: "struct" feature_name: "use" }" end ext: external MY_STRUCT is -- inline declaration of external type external "plug_in" alias "{ location: "./" module_name: "struct" attribute_type: "my_struct" }" end end