create 18.11

git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@2112 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
eiffel-org
2018-12-13 14:11:52 +00:00
parent d78b455645
commit a961d92e4a
2938 changed files with 62188 additions and 0 deletions

View File

@@ -0,0 +1,581 @@
[[Property:title|CECIL interface overview]]
[[Property:weight|3]]
[[Property:uuid|7d8b4785-6f05-02c9-ba1c-12bad3d4b331]]
==Eiffel basic types==
The EIFFEL include files define types for every EIFFEL types:
* An Eiffel <eiffel>INTEGER</eiffel> is an ''EIF_INTEGER'',
* An Eiffel <eiffel>CHARACTER</eiffel> is an ''EIF_CHARACTER'',
* An Eiffel <eiffel>REAL</eiffel> is an ''EIF_REAL'',
* An Eiffel <eiffel>DOUBLE</eiffel> is an ''EIF_DOUBLE'',
* Eiffel references (any Eiffel objects that are not from a basic type) are ''EIF_REFERENCE'' (not protected, and can be moved),
* An Eiffel <eiffel>POINTER</eiffel> is an ''EIF_POINTER,''
* An Eiffel <eiffel>BOOLEAN</eiffel> is an ''EIF_BOOLEAN'',
* A Protected Eiffel object is an ''EIF_OBJECT'' (does not move, and should be accessed through eif_access. ).
Generally, you should use these types when implementing external C functions bound to be used from Eiffel or when you want to manipulate Eiffel objects from the C side. EIF_REFERENCE, EIF_OBJECT, EIF_POINTER all correspond in C to a (char *), but their semantic remains different in Eiffel.
{{note|In the following code samples, the class <eiffel>OBJECT</eiffel> is a placeholder for one of your type that you wish to use via CECIL.}}
{{sample|Calling C external `foo` from Eiffel, which takes a pointer and an eiffel object of type OBJECT as arguments and returns an INTEGER. }}
<code>
c_foo (ptr: POINTER; obj: OBJECT): INTEGER
external
"C | %"your_file.h%""
alias
"foo"
end
</code>
In the C side, The C function `foo` is defined as follow:
<code lang="c">
EIF_INTEGER foo (EIF_POINTER ptr, EIF_OBJECT obj)
{
/* some code */
}
</code>
In some cases, you may not be able to change the signature of a C function you want to use. In this case, you must describe its actual signature in the Eiffel code. On the C side, foo is already defined as below:
<code lang="c">
int foo (void *arg1, char c, FILE *file)
{
/* some code */
}
</code>
To match the signature, you must declare it in Eiffel as:
<code>
c_foo (arg1: POINTER; c: CHARACTER; file: POINTER): INTEGER
external
"C (void *, char, FILE *) : int | %""your_file.h%""
alias
"foo"
end
</code>
Not doing this would generally produce warnings during the C compilation, and it could crash with some C compilers.
To perform the conversion, here is the actual Eiffel types mapping to C types:
* <eiffel>POINTER</eiffel> is compatible with any C pointer ( ''char *'').
* <eiffel>INTEGER</eiffel> is a long.
* <eiffel>CHARACTER</eiffel> is an ''unsigned char''.
* <eiffel>DOUBLE</eiffel> is a ''double''.
* <eiffel>REAL</eiffel> is a ''float''.
* <eiffel>BOOLEAN</eiffel> is an ''unsigned char (EIF_TRUE = '\01', EIF_FALSE = '\0')'' .
These are the current correspondences but they may change. The definition of each Eiffel type is located in `$ISE_EIFFEL/bench/spec/$PLATFORM/include/eif_portable.h` .
===More about EIF_OBJECT, EIF_REFERENCE, and basic expanded types===
It is sometimes difficult to tell the difference between an ''EIF_OBJECT'' and an ''EIF_REFERENCE''.
An ''EIF_REFERENCE'' is an Eiffel reference. It corresponds to an Eiffel object in the Eiffel side. <eiffel>eif_attribute</eiffel>, <eiffel>eif_reference_function</eiffel>, <eiffel>eif_string</eiffel>, <eiffel>eif_wean</eiffel> all return ''EIF_REFERENCEs''. An ''EIF_REFERENCE'' can be used "as is" by the Eiffel run-time. <eiffel>eif_attribute</eiffel>, <eiffel>eif_xx_function</eiffel> take ''EIF_REFERENCEs'' as arguments, never ''EIF_OBJECTs''. The return value of a C external is to be an ''EIF_REFERENCE'', if it is not a basic expanded type. To protect an ''EIF_REFERENCE'', use <eiffel>eif_protect</eiffel>.
An ''EIF_OBJECT'' is a safe and static indirection to an Eiffel reference. As the GC may move an Eiffel reference, this indirection is updated at every collection so that you do not need to know whether an Eiffel reference has moved or not. You must pass through this indirection to access the Eiffel reference (see <eiffel>eif_access</eiffel>). Not doing so is completely unsafe since an Eiffel reference may be obsolete after a collection. <eiffel>eif_create</eiffel>, <eiffel>eif_adopt</eiffel>, and <eiffel>eif_protect</eiffel> returns an ''EIF_OBJECT''. The argument of a C external (on the C side) , which is not a basic expanded type, is also an ''EIF_OBJECT''. The Eiffel run-time temporarily protects the Eiffel objects that are passed to a C external , that is why the signature of a C external has no ''EIF_REFERENCE'' in it, but ''EIF_OBJECT'' instead. After the C external call, the run-time unprotects the Eiffel object. If you intend to use in the C side an ''EIF_OBJECT'' given by a C external afterwards, you must protect it with <eiffel>eif_adopt</eiffel>. To unprotect an ''EIF_OBJECT'' , which is not a C external argument, use <eiffel>eif_wean</eiffel>.
The basic expanded types are <eiffel>INTEGER</eiffel>, <eiffel>INTEGER_64</eiffel>, <eiffel>INTEGER_16</eiffel>, <eiffel>INTEGER_8</eiffel>, <eiffel>REAL</eiffel>, <eiffel>DOUBLE</eiffel>, <eiffel>CHARACTER</eiffel>, <eiffel>BOOLEAN</eiffel>, <eiffel>POINTER</eiffel>. They are passed to C externals by values. There is no need to protect instances of these types. When the <eiffel>POINTER</eiffel> is a pointer to an Eiffel object (ex: $my_object), then the direct Eiffel reference is passed to C, with no protection and this reference may move. Use <eiffel>eif_protect</eiffel> to manually protect it. To unprotect it, call <eiffel>eif_wean. </eiffel>
==Protecting the Eiffel objects==
You can use the CECIL functions directly from a C program as well as from a C external called from Eiffel. If you encounter problems, they may be related to the handling of garbage collection. The programmer who uses CECIL has to be aware that all Eiffel objects can be moved or collected asynchronously by the Garbage Collector (GC).
The cecil library provides the user with numerous macros and functions, which relieve the programmer from these kinds of low-level considerations (most of them are declared in $ISE_EIFFEL/bench/spec/$PLATFORM/include/eif_cecil. h).
===Eiffel objects passed in a C external===
An Eiffel object which is passed as an argument of a C external is automatically protected: the value passed to C is not a direct Eiffel reference. In fact, it is a temporary indirection pointer, which is only valid until the C external returned. This indirection pointer is to be used to access the direct reference of the Eiffel object with ''eif_access (eiffel_object)'' where ''eiffel_object'' is the argument (an ''EIF_OBJECT)'' of the C external which corresponds to the Eiffel object. Only Eiffel objects passed to C is automatically protected. This excludes basic expanded types, since they cannot be moved.
===Accessing the direct reference to an Eiffel object: eif_access===
'''# include "eif_hector. h"'''
'''EIF_REFERENCE eif_access (EIF_OBJECT object) /* Macro */'''
The GC moves the objects every time it runs a collection cycle. A collection cycle can only occur during an Eiffel call. This includes calls to Eiffel routines and calls to CECIL functions (other than ''eif_access''). Thus, it may be unsafe to access a "raw" reference to an Eiffel object, (of type ''EIF_REFERENCE'') "as is", since the latter can be obsolete after each collection. To avoid this, you must access a direct reference through a "protection", which is a safe, non-moving pointer (of type ''EIF_OBJECT''). Call the macro ''eif_access'' as follows: ''eif_access (protection)'' , where ''protection'' is either a value returned by <eiffel>eif_create</eiffel>, <eiffel>eif_adopt</eiffel> or <eiffel>eif_protect,</eiffel> or an Eiffel object which is an argument of a C external.
Use ''eif_access'' to pass an Eiffel object to an Eiffel routine or to return the value of a C external. It is also unsafe to pass a direct Eiffel reference ( ''EIF_REFERENCE'') to a C function which is not an Eiffel routine. Pass a protected indirection instead ( ''EIF_OBJECT''). However, if you still intend to pass a direct reference, be very careful and make sure that you do not perform any Eiffel call after passing the reference to the C function and before reading it.
'''For example, in the following external:'''
<code>
c_foo (ptr: POINTER; obj: OBJECT): INTEGER
external
"C | %""your_file.h%""
alias
"foo"
end
</code>
the Eiffel run-time will protect obj, which can asynchronously move, and give a static and safe indirection to C.
'''Here is an example of how accessing obj: OBJECT:'''
<code lang="c">
EIF_INTEGER foo (EIF_POINTER ptr, EIF_OBJECT obj);
{
/* Print the Eiffel object `obj', with the feature `print'
* from ANY. (do not forget to put `visible' the class
* ANY in the project configuration file.
*/
EIF_PROCEDURE ep;
EIF_TYPE_ID tid;
tid = eif_type_id ("ANY");
ep = eif_procedure ("print", tid);
(ep) (eif_access(obj),eif_access(obj));
}
</code>
'''Important rules when using eif_access:'''
{{note|The first argument of ''(ep)'' is the target of the function (the eiffel object to which you want to apply the Eiffel feature ''(ep)'') and the second argument corresponds to the first argument of `print`. Any Eiffel object could have been the 1st argument of ''(ep)'' since all of them inherit ''ANY''. }}
* '''Never pre compute the value returned by eif_access. ''' <br/>
'''Example:''' <br/>
<u>Example:</u> <br/>
Instead of the code above, it would have been dangerous to write:
<code lang="c">
EIF_REFERENCE e_ref = eif_access (obj);
...
(ep) (e_ref, e_ref);
</code>
because e_ref is the direct reference to the Eiffel object when calling ''eif_access(). '' There is not guarantee that it will still be valid when the call to ''(ep)'' is done: meanwhile, e_ref may have been moved by the GC. <br/>
* '''Never use eif_access with encapsulated eiffel calls:''' <br/>
(eif_access in not an eiffel call)
'''Example:'''
<code lang="c">
(ep) (eif_access (a), eif_string ("Hello world"));
/* eif_string is a macro returning a direct reference to an Eiffel string,
* which corresponds to the C string passed as its argument.
*/
</code>
Nothing guarantees that the direct reference returned by `eif_access (a)` will be still valid when executing (ep): it may be obsolete after the Eiffel call eif_string ("Hello world"), which may invoke a collection cycle.
The correct code is
<code lang="c">
EIF_REFERENCE my_string;
/* some code */
my_string = eif_string ("Hello world");
(ep) (eif_access (a), my_string);
</code>
In this case, you do not need to protect `my_string` since the GC is not likely to be triggered after the call to ''eif_string'' and before `my_string` is given as argument in ''(ep). '' A collection is triggered only during Eiffel calls. If an Eiffel call had been performed, you would have had to use ''eif_protect'' (see paragraph 3. 2):
<code lang="c">
EIF_REFERENCE my_string;
EIF_OBJECT i_my_string;
/* some code */
my_string = eif_string ("Hello world");
i_my_string = eif_protect (my_string); /* Protect `my_string'. */
/* Some eiffel calls */
(ep) (eif_access (a), eif_access (i_my_string));
eif_wean (i_my_string); /* Release protection. */
</code>
===Keeping a reference from C after an external call: eif_adopt===
'''# include "eif_hector. h"'''
EIF_OBJECT eif_adopt (EIF_OBJECT object)
When passing Eiffel objects to C, you may need to keep a reference to them after the C external is called. Since the Eiffel run-time automatically will unprotect the Eiffel object references passed to a C external after execution, if one of the Eiffel objects is not referenced any longer from Eiffel, then the garbage collector will collect it because it is not aware that you may still need to reference this object from the C side.
Called within a C external, the function ''eif_adopt'' creates a user protection for the Eiffel object ''object'' passed to C ( ''object'' is a C external argument). This way, the GC cannot collect the Eiffel reference returned by ''eif_access(object)'' when the C external returned. It tells the GC to keep artificially a reference to this Eiffel reference from C. It returns the new indirection pointer (say ''returned_value'') that must be used afterwards to access this direct Eiffel reference with ''eif_access (return_value)''. It is important to note that ''eif_adopt'' already takes an indirection pointer as unique argument. This is a temporary protection pointer: you can access the direct Eiffel reference with ''eif_access (object)'' only within the code of the C external. When the C external returns, ''eif_access (object)'' is NULL but ''eif_access (returned_value)'' remains valid until you release it with <eiffel>eif_wean</eiffel>.
'''Example:'''
In Eiffel:
<code>
c_foo (ptr: POINTER; obj: OBJECT): INTEGER
external
"C | %"your_file.h%""
alias
"foo"
end
c_display_and_release_obj
external
"C | %"your_file.h%""
alias
"display_and_release_obj"
end
</code>
On the C side:
<code lang="c">
EIF_OBJECT my_obj; /* Protection of the object of type OBJECT. */
EIF_INTEGER foo (EIF_POINTER ptr, EIF_OBJECT obj)
{
my_obj = eif_adopt (obj); /* Keeping a reference on it for
* for later use.
*/
/* some code */
}
void display_and_release_obj (void)
{
/* Display global object. */
EIF_PROCEDURE ep;
EIF_TYPE_ID tid;
tid = eif_type_id ("OBJECT");
ep = eif_procedure ("print", tid);
(ep) (eif_access(my_obj),eif_access(my_obj)); /* Print global object.*/
eif_wean (my_obj); /* Remove the protection on global object.*/
}
</code>
Between the call of `c_foo` and `c_display_obj`, the global object `(eif_access (my_obj))` may not be referenced from Eiffel any longer. To prevent the GC from collecting it before the call to `c_display_and_release_obj`, you must protect it with `eif_adopt` in the C function `foo`.
==Other CECIL functions:==
===Creating Eiffel objects from C: eif_create===
''' # include "eif_cecil. h"'''
EIF_OBJECT eif_create (EIF_TYPE_ID type_id)
All CECIL calls are not completed using C externals. It is possible to create and manipulate Eiffel objects from a C program and still reap benefits from the garbage collector and design by contract methodology provided by Eiffel (see also [[Compiling an Eiffel system for CECIL|How to run a CECIL program]] ). This function does not call any creation procedure.
The CECIL function ''eif_create'' takes a type identifier ''type_id'' as argument (generally returned by <eiffel>eif_type_id</eiffel>). It returns a static indirection pointer which is to be used afterwards to access the newly created Eiffel object with ''eif_access (returned_value)'' where ''returned_value'' is the value returned by ''eif_create'' . This means that when creating an eiffel object from C, the eiffel object is automatically protected: there is no need to call <eiffel>eif_adopt</eiffel> or <eiffel>eif_protect</eiffel> on it. This function does not call any creation procedure. To do so, you need to explicitly call it with <eiffel>eif_procedure</eiffel>. The garbage collector will not collect the newly created object until you call <eiffel>eif_wean</eiffel> on it.
'''Example:'''
Creating an object of type "OBJECT":
<code lang="c">
#include eif_setup.h" /* for EIF_INITIALIZE and EIF_DISPOSE_ALL */
#include "eif_eiffel.h" /* for other exported routines from the Eiffel run-time */
main (int argc,char **argv,char **envp)
{
EIF_TYPE_ID tid;
EIF_OBJECT my_obj;
EIF_INITIALIZE(failure) /* Initialization of Eiffel run-time.
* This is to be done before any CECIL call.
*/
tid = eif_type_id ("OBJECT");
if (tid == EIF_NO_TYPE)
eif_panic ("No type id.");
my_obj = eif_create (tid); /* Create eiffel object, returns an indirection. */
/* some code */
eif_wean (my_obj); /* We do not need it any more. */
EIF_DISPOSE_ALL /* Reclaim memory allocated by Eiffel run-time. */
}
</code>
{{note|`eif_create` does not call any creation procedure. It just allocates memory and initializes an object. }}
===Protecting the objects returned by Eiffel functions.===
'''# include "eif_hector. h"'''
''' EIF_OBJECT eif_protect (EIF_REFERENCE object)'''
This function is used to tell explicitly the GC that you want to keep a reference to an eiffel object from the C. It returns a static indirection pointer which is to be used afterwards to access the direct Eiffel reference object with eif_access (returned_value) where returned_value is the value returned by eif_protect . With this call, the GC artificially references object, so that it cannot collect it. It is unsafe to access directly (i.e without using eif_access) the Eiffel reference object, which may be obsolete after any collection cycle (the GC moves the objects). Ignore this rule, if you are sure that there is no Eiffel call after you pass the direct Eiffel reference to a C function and before you read it.
To release this artificial reference, call eif_wean (returned_value)
eif_protect is to be called on an EIF_REFERENCE returned by eif_attribute, eif_string, or the returned value of eif_reference_function.
See also eif_adopt, eif_create, eif_wean, eif_access.
'''Example:''' Assume that you want to access an attribute `tab` of type <eiffel>ARRAY [INTEGER]</eiffel> in the class <eiffel>OBJECT</eiffel>.
<code lang="c">
#include eif_setup.h"
#include "eif_eiffel.h"
main (int argc,char **argv,char **envp)
{
EIF_TYPE_ID tid;
EIF_OBJECT my_obj;
EIF_PROCEDURE emake; /* Creation procedure of "OBJECT". */
EIF_REFERENCE tab; /* direct reference to `tab' from "OBJECT". */
EIF_OBJECT i_tab; /* Protected indirection to `tab'. */
EIF_INITIALIZE(failure)
tid = eif_type_id ("OBJECT");
if (tid == EIF_NO_TYPE)
eif_panic ("No type Id.");
my_obj = eif_create (tid);
emake = eif_procedure ("make", tid); /* On the eiffel side: make is do ... end.. */
(emake) (eif_access (my_obj)); /* Call `make' on `eif_access(my_obj)'.*/
tab = eif_attribute( eif_access (my_obj), "tab", EIF_REFERENCE, NULL);
/* Return the attribute `tab' of type EIF_REFERENCE
* of the object `eif_access (my_obj)'.
*/
i_tab = eif_protect (tab); /* Here, protect `tab'. */
/* some code */
eif_wean (my_obj);
eif_wean (i_tab); /* We do not need it any more. */
EIF_DISPOSE_ALL /* Reclaim memory allocated by Eiffel run-time. */
}
</code>
{{note|Although you must protect Eiffel references returned by eif_attribute, you do not have to protect attributes of basic types - they are not Eiffel references and not supposed to move. }}
===Getting the type id of an Eiffel type: eif_type_id===
'''# include "eif_gen_conf. h"''' # include "eif_gen_conf. h"
EIF_TYPE_ID eif_type_id (char *type_string)
Return the type identifier corresponding to the type described in type_string. If the type does not exist, is not visible or an instance of it is not declared in the root class, it returns EIF_NO_TYPE.
COMPATIBILITY:
eif_type_id is equivalent to eif_type_by_name.
'''Example:''' type_id of STD_FILES so as to call 'put_string'.
<code lang="c">
EIF_PROCEDURE p_put_string; /* 'put_string' from STD_FILES. */
EIF_TYPE_ID tid;
EIF_REFERENCE_FUNCTION fn_io; /* once function `io' from ANY (and STD_FILES by inheritance). */
EIF_REFERENCE o_io; /* Eiffel object `io' returned by once function*/
EIF_REFERENCE o_str; /* Eiffel string */
EIF_OBJECT i_io, i_str; /* safe indirection pointers to ``io' and Eiffel string. */
tid = eif_type_id ("STD_FILES");
if (tid == EIF_NO_TYPE)
eif_panic ("Type not in system.");
fn_io = eif_reference_function ("io", tid);
o_io = (fn_io) (root_obj); /* `root_obj' is the root object of the CECIL system
* automatically initialized in EIF_INITIALIZED
* if it does not exists */
i_io = eif_protect (o_io); /* Protect `io' . */
o_str = eif_string ("Hello World"); /* Create Eiffel string */
i_str = eif_protect (o_str); /* Protect Eiffel string. */
p_put_string = eif_procedure ("put_string", tid);
if (p_put_string == (EIF_PROCEDURE) 0) /* No routine found. */
eif_panic ("put_string not visible"); /* Raised if "visible exception" disabled. */
(p_put_string) (eif_access (i_io), eif_access (i_str));
</code>
eif_type_id is also used for returning the type identifier of generic types but you need to specify the generic parameter, otherwise it returns EIF_NO_TYPE.
'''Example:'''
<code lang="c">
EIF_PROCEDURE p_make; /* 'make' from ARRAY [INTEGER] . */
EIF_TYPE_ID tid;
tid = eif_type_id ("ARRAY[INTEGER]");
p_make = eif_procedure ("make", tid);
</code>
===Getting the type id of a generic type : eif_generic_type.===
Obsolete: see eif_type_id.
===Raising an eiffel panic: eif_panic.===
''' # include "eif_except. h"'''
void eif_panic(char *msg)
<nowiki># include "eif_threads. h"</nowiki>
void eif_thr_panic (char *msg)
Raise an Eiffel panic with Eiffel exception trace with message msg. In MT mode, use eif_thr_panic instead.
===Releasing an Eiffel indirection pointer: eif_wean===
'''# include "eif_hector. h"'''
EIF_REFERENCE eif_wean(EIF_OBJECT object)
Tell the GC to remove the artificial reference to the nested Eiffel reference returned by eif_access (object). Then, the GC will be able to collect this nested object, as soon as it is not referenced from Eiffel any longer.
{{note|Object must have been previously created with eif_adopt, eif_protect or eif_create. }}
eif_wean (object) returns an Eiffel reference, which corresponds to eif_access (object). After a call to eif_wean (object), eif_access (object) is NULL, which does not mean that the nested Eiffel object is Void, but that the indirection pointer does not reference it any longer. It is possible to reuse object later on. <br/>
Calling eif_wean (external_argument) where external_argument is an Eiffel object given by a C external can cause erratic behaviors. Indeed, external_argument is an indirection pointer, which is automatically deleted after the external call (not the nested Eiffel object), deleting it prematurely can corrupt the indirection pointers stack. <br/>
See also <eiffel>eif_access</eiffel>.
'''Example:''' C external returning an Eiffel string.
In Eiffel:
<code>
foo : STRING
external
"C | %"a file.h%""
end
</code>
In C:
<code lang="c">
EIF_REFERENCE foo () {
EIF_REFERENCE str;
EIF_OBJECT i_str;
str = eif_string ("Hello world");
i_str = eif_protect(str);
/* Some operations on `i_str' */
return eif_wean (i_str); /* Returns direct reference to the Eiffel string.
* No need to keep an extra reference from the C. */
}
</code>
===Getting the attribute from an Eiffel object: eif_attribute===
```
# include "eif_cecil. h"
EIFFEL_TYPE eif_attribute (EIF_REFERENCE object, char *name, EIFFEL_TYPE, int *status)
```
Return the attribute of an Eiffel object.
The `eif_attribute` macro returns the attribute of object of name, which is of type EIFFEL_TYPE.
EIFFEL_TYPE is the type of the Eiffel attribute. It can be: EIF_INTEGER, EIF_POINTER, EIF_CHARACTER, EIF_BOOLEAN, EIF_DOUBLE, EIF_REAL or EIF_REFERENCE.
If status is NULL then no status is set. Otherwise the status of the function is put in *status:
*status = EIF_NO_ATTRIBUTE => no attribute found.
*status = EIF_CECIL_OK => attribute found.
*status = EIF_CECIL_ERROR => an undefined error occurred, object may be invalid.
If the visible exception is enabled, then a visible exception is raised upon failure (EIF_NO_ATTRIBUTE, EIF_CECIL_ERROR).
RETURN VALUE:
Upon failure, it returns (EIFFEL_TYPE) 0, otherwise, the attribute is returned. If the return value is not a basic type, you must protect it with eif_protect.
COMPATIBILITY:
`eif_attribute (object, name, type, NULL)` is equivalent to `eif_field (object, name, type)`.
{{tip|You cannot access a constant attribute, or the result of a function (once or not) with eif_attribute. Use eif_procedure or eif_xx_function instead. }}
<br/>
{{tip|EIF_BOOLEAN attribute_exists (EIF_REFERENCE object, char *name) returns EIF_TRUE or EIF_FALSE depending if the attribute exists or not, is visible or not. }}
===Getting the address of an Eiffel routine===
```
#include "eif_cecil. h"
EIF_PROCEDURE eif_procedure (char *rout_name, EIF_TYPE_ID type_id)
EIF_REFERENCE_FUNCTION eif_reference_function (char *rout_name, EIF_TYPE_ID type_id)
EIF_INTEGER_FUNCTION eif_integer_function (char *rout_name, EIF_TYPE_ID type_id)
EIF_CHARACTER_FUNCTION eif_character_function (char *rout_name, EIF_TYPE_ID type_id)
EIF_REAL_FUNCTION eif_real_function (char *rout_name, EIF_TYPE_ID type_id)
EIF_DOUBLE_FUNCTION eif_double_function (char *rput_name, EIF_TYPE_ID type_id)
EIF_BIT_FUNCTION eif_bit_function (char *rout_name, EIF_TYPE_ID type_id)
EIF_BOOLEAN_FUNCTION eif_boolean_function (char *rout_name, EIF_TYPE_ID type_id)
EIF_POINTER_FUNCTION eif_pointer_function (char *rout_name, EIF_TYPE_ID type_id)
```
Return the address of the Eiffel routine by giving its name rout_name and the type id type_id of the class, in which it is declared. Returns a NULL pointer or raises a visible exception (if enabled) when there is no corresponding routine with name rout_name or the routine is not visible. The first argument of an Eiffel routine has to be the target of the Eiffel routine.
The Eiffel object returned by an Eiffel function must be protected afterwards with `eif_protect` (this only applies for functions whose addresses are returned by `eif_reference_function`, since the other function types returns basic types, which are not Eiffel objects).
{{note|The address returned by these functions must be called between parenthesis. }}
{{caution|Be sure that the Eiffel routine is not a C External. In this case, you should call directly the C external instead of its Eiffel wrapper. }}
===Enabling/Disabling the visible exception===
```
#include "eif_cecil. h"
void eif_enable_visible_exception ()
void eif_disable_visible_exception ()
```
Respectively, enable and disable the visible exception.
By default, the visible exception is disabled (since v4. 5).
===Creating an Eiffel string: eif_string===
```
#include "eif_plug. h"
EIF_REFERENCE eif_string (char *string) /* Macro */
```
Return the direct reference to an Eiffel string by giving the corresponding C string . The result of eif_string does not reference the C string passed as argument: it copies it, before creating the Eiffel string.
{{note|The return value must be protected with eif_protect for later use. <br/>The C string must be manually freed by the user, if it has been dynamically allocated. }}
COMPATIBILITY:
`eif_string ("ABC")` is equivalent to `RTMS ("ABC")` and `eif_make_string ("ABC", strlen ("ABC"))`.
===Getting the return-type of an attribute: eif_attribute_type===
```
#include "eif_cecil. h"
int eif_attribute_type (char *attr_name, EIF_TYPE_ID tid)
#define EIF_REFERENCE_TYPE 1
#define EIF_CHARACTER_TYPE 2
#define EIF_BOOLEAN_TYPE 3
#define EIF_INTEGER_TYPE 4
#define EIF_REAL_TYPE 5
#define EIF_DOUBLE_TYPE 6
#define EIF_EXPANDED_TYPE 7
#define EIF_BIT_TYPE 8
#define EIF_POINTER_TYPE 0
#define EIF_NO_TYPE (-1)
```
Return the type of the attribute described by its name attr_name and the type identifier tid of the class where it is defined. The return type is an int (see above for correspondences). In case of failure, EIF_NO_TYPE is returned - not such given attribute name, routine name instead of attribute name, or so on.
'''Example:''' Get the type of count from STRING
<code lang="c">
int i;
i = eif_attribute_type ("count", eif_type_id ("STRING");
printf ("type is %d\n"); /* Should be EIF_INTEGER_TYPE since it returns an Eiffel Integer */
</code>
{{tip|*(EIFFEL_TYPE *) eif_attribute_safe (EIF_REFERENCE object, char *name, int type_int, int *status) can be used for debugging or type checking. It returns the attribute reference of name from the object of type type_int. status contains the status of the function call: it can be EIF_CECIL_OK, EIF_CECIL_ERROR, EIF_NO_ATTRIBUTE or EIF_WRONG_TYPE (type_int does not match with real type of object). }}
===Getting the class name corresponding to a type id: eif_name===
```
#include "eif_cecil. h"
char *eif_name (EIF_TYPE_ID tid)
```
Return the corresponding name (C string) of the Eiffel class, given a type identifier type_id. If the type identifier is a generic type identifier, no generic parameter type is given. Return NULL if an invalid type identifier is given.
'''Example:'''
`printf ("the class name with type id 1 is %s\n", eif_name (1); /* Should print "ANY" on most compiler versions */`
COMPATIBILITY:
`eif_name` is equivalent to `eif_name_by_tid`.
===Getting the type id of an Eiffel object: eif_type, eif_type_by_reference.===
```
#include "eif_cecil. h"
EIF_TYPE_ID eif_type (EIF_OBJECT object)
EIF_TYPE_ID eif_type_by_reference (EIF_REFERENCE reference)
```
`eif_type` returns the type identifier, given an indirection pointer to an Eiffel object.
`eif_type_by_reference` returns the type identifier, given the direct reference to an Eiffel object reference.
COMPATIBILITY:
`eif_type` is equivalent to `eif_type_by_object.eif_type (object)` is equivalent to `eif_type_by_reference (eif_access (object))`.
===Converting a C array into an Eiffel array: eif_make_from_c.===
```
eif_make_from_c(eif_array, c_array, int nelts, int type) /* Macro */
```
(since 4. 5)
`eif_array` is an `EIF_REFERENCE`, `c_array` is a C array of type `(type *)`, `nelts is the number of elements in the array.

View File

@@ -0,0 +1,24 @@
[[Property:title|attribute_exists]]
[[Property:weight|-15]]
[[Property:uuid|7cdf93a7-6f63-869a-5443-b8908a086d18]]
==Overview==
<code lang="text">
#include "eif_cecil.h"
EIF_BOOLEAN attribute_exists (EIF_REFERENCE object, char * name);
</code>
==Description==
The <code lang="text">attribute_exists()</code> macro returns <code lang="text">EIF_TRUE</code> when the attribute of name <code lang="text">name</code> exists in the Eiffel object (reference) <code lang="text">object</code>.
==Return value==
<code lang="text">EIF_TRUE</code> or <code lang="text">EIF_FALSE</code>.
==Conformance==
ISE Eiffel 4.5 and later.
{{SeeAlso|<br/>
[[eif_attribute]] }}

View File

@@ -0,0 +1,28 @@
[[Property:title|eif_access]]
[[Property:weight|-14]]
[[Property:uuid|2f74eeb4-2508-bf32-adf2-87959cfb2593]]
==Synopsis==
<code lang="text">
#include "eif_hector.h"
EIF_REFERENCE eif_access (EIF_OBJECT obj);
</code>
==Description==
The <code lang="text">eif_access</code> macro accesses the Eiffel object <code lang="text">obj</code>.
==Return value==
The Eiffel reference (<code lang="text">EIF_REFERENCE</code>) protected by <code lang="text">obj</code> which can be passed to Eiffel routines.
==Conformance==
ISE Eiffel 4.1 and later.
{{SeeAlso| <br/>
[[eif_wean]]<br/>
[[eif_adopt]]<br/>
[[eif_protect]] }}

View File

@@ -0,0 +1,28 @@
[[Property:title|eif_adopt]]
[[Property:weight|-13]]
[[Property:uuid|dc8ef8a9-7082-2a27-4e45-8f1d4472dbda]]
==Synopsis==
<code lang="text">
#include "eif_hector.h"
EIF_OBJECT eif_adopt (EIF_OBJECT obj);
</code>
==Description==
The <code lang="text">eif_adopt</code> function adopts <code lang="text">obj</code>. By adopting it, the user prevents <code lang="text">obj</code> from being unprotected automatically by the Eiffel run-time. The run-time protects automatically the Eiffel objects passed to a C external before entering the external and unprotects them after exiting the C external. To keep this protection later on, you must call <code lang="text">eif_adopt</code>.
==Return value==
An <code lang="text">EIF_OBJECT</code>. This return value can be used later to access the nested, protected Eiffel reference with [[eif_access]].
==Conformance==
ISE Eiffel 4.1 and later.
{{SeeAlso| <br/>
[[eif_access]]<br/>
[[eif_protect]]<br/>
[[eif_wean]] }}

View File

@@ -0,0 +1,39 @@
[[Property:title|eif_attribute_type]]
[[Property:weight|-11]]
[[Property:uuid|28b3840f-648f-dc4d-8c83-70532a5e8e63]]
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
int eif_attribute_type (char *attr, EIF_TYPE_ID tid);
</code>
==Description==
The <code lang="text">eif_attribute_type</code> function returns the type of the attribute <code lang="text">attr</code>, from the Eiffel type, which type identifier is <code lang="text">tid</code>.
==Return value==
Sucessful: One of the following:
# <code lang="text">EIF_INTEGER_TYPE</code>
# <code lang="text">EIF_CHARACTER_TYPE</code>
# <code lang="text">EIF_BOOLEAN_TYPE</code>
# <code lang="text">EIF_DOUBLE_TYPE</code>
# <code lang="text">EIF_REAL_TYPE</code>
# <code lang="text">EIF_REFERENCE_TYPE</code>
# <code lang="text">EIF_EXPANDED_TYPE</code>
# <code lang="text">EIF_BIT_TYPE</code>
Failing: <code lang="text">EIF_NO_TYPE</code>
==Conformance==
ISE Eiffel 4.5 and later.
{{SeeAlso| <br/>
[[eif_protect]]<br/>
[[attribute_exists]]<br/>
[[eif_procedure]]<br/>
[[eif_*_function]] }}

View File

@@ -0,0 +1,62 @@
[[Property:title|eif_attribute]]
[[Property:weight|-12]]
[[Property:uuid|c843f272-8ac2-c30e-e71f-bd6c567e9de3]]
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
EIFFEL_TYPE eif_attribute (EIF_REFERENCE object, char * name, EIFFEL_TYPE, int * status);
</code>
==Description==
The <code lang="text">eif_attribute</code> macro returns the attribute of name <code lang="text">name</code>, which is of type <code lang="text">EIFFEL_TYPE</code>.
<code lang="text">EIFFEL_TYPE</code> is the type of the Eiffel attribute. It can be one of the following:
# <code lang="text">EIF_INTEGER</code>
# <code lang="text">EIF_CHARACTER</code>
# <code lang="text">EIF_BOOLEAN</code>
# <code lang="text">EIF_DOUBLE</code>
# <code lang="text">EIF_REAL</code>
# <code lang="text">EIF_REFERENCE</code>
If <code lang="text">status</code> is <code lang="text">NULL</code> then no status is set. Otherwise the status of the call is put into <code lang="text">*status</code>. Its value is one of the following:
# <code lang="text">EIF_NO_ATTRIBUTE</code>
# <code lang="text">EIF_CECIL_OK</code>
If the visible exception is enabled, then a visible exception is raised upon failure (<code lang="text">EIF_NO_ATTRIBUTE</code>, <code lang="text">EIF_CECIL_ERROR</code>).
==Return value==
Successful: the Eiffel attribute.
Failing: (<code lang="text">EIFFEL_TYPE</code>) 0
==Notes==
If the return value is an <code lang="text">EIF_REFERENCE</code>, you must protect it with [[eif_protect]].
You cannot access a constant attribute, or the result of a once function with <code lang="text">eif_attribute</code>.
==Conformance==
ISE Eiffel 4.5 and later.
==Compatibility==
<code lang="text">
eif_attribute (object, name, type, NULL)
</code>
is equivalent to:
<code lang="text">
eif_field (object, name, type)
</code>
which is deprecated.
{{SeeAlso| <br/>
[[eif_protect]]<br/>
[[attribute_exists]]<br/>
[[eif_procedure]]<br/>
[[eif_*_function]] }}

View File

@@ -0,0 +1,30 @@
[[Property:title|eif_create]]
[[Property:weight|-7]]
[[Property:uuid|b928f4b9-2830-5723-6f02-57eac618b116]]
==Synopsis==
<code lang="text">
#include "eif_cecil. h"
EIF_OBJECT eif_create (EIF_TYPE_ID tid);
</code>
==Description==
The <code lang="text">eif_create</code> function creates an Eiffel object, which type identifier is <code lang="text">tid</code>.
==Return value==
It returns an Eiffel object, which is already protected.
==Notes==
You cannot pass the return value to Eiffel routines as is: you must call [[eif_access]] to pass it to Eiffel routine.
To release the protection of an Eiffel object created with <code lang="text">eif_create</code>, call [[eif_wean]]. It will be collected during the next collection.
==Conformance==
ISE Eiffel 4.1 and later.
{{SeeAlso| <br/>
[[eif_wean]]<br/>
[[eif_type_id]] }}

View File

@@ -0,0 +1,32 @@
[[Property:title|eif_disable_visible_exception]]
[[Property:weight|-6]]
[[Property:uuid|6b8323d9-1963-c6b8-0198-f07895916c46]]
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
void eif_enable_visible_exception ();
void eif_disable_visible_exception ();
</code>
==Description==
The [[eif_enable_visible_exception]] routine enables the visible exception, while [[eif_disable_visible_exception]] disables it. These routines can be used for debugging purpose. A visible exception is raised when the user tries to access to an Eiffel attribute or a Eiffel routine address which is not visible.
The visible exception is disabled by default.
==Conformance==
ISE Eiffel 4.5 and later.
==Compatibility==
In ISE Eiffel 4.3 and 4.4, the visible exception is enabled by default.
{{SeeAlso| <br/>
[[eif_attribute]] <br/>
[[eif_procedure]] <br/>
[[eif_*_function]] }}

View File

@@ -0,0 +1,33 @@
[[Property:title|eif_enable_visible_exception]]
[[Property:weight|-4]]
[[Property:uuid|97b5a74c-d7ad-abf4-9390-59266b67c7c7]]
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
void eif_enable_visible_exception ();
void eif_disable_visible_exception ();
</code>
==Description==
The [[eif_enable_visible_exception]] routine enables the visible exception, while [[eif_disable_visible_exception]] disables it. These routines can be used for debugging purpose. A visible exception is raised when the user tries to access to an Eiffel attribute or a Eiffel routine address which is not visible.
The visible exception is disabled by default.
==Conformance==
ISE Eiffel 4.5 and later.
==Compatibility==
In ISE Eiffel 4.3 and 4.4, the visible exception is enabled by default.
{{SeeAlso| <br/>
[[eif_attribute]] <br/>
[[eif_procedure]] <br/>
[[eif_*_function]] }}

View File

@@ -0,0 +1,125 @@
[[Property:title|eif_*_function]]
[[Property:weight|15]]
[[Property:uuid|643603a5-de12-1ffc-2da3-92c8475078e8]]
==Overview==
This page documents all CECIL functions of the form eif_*_function where "*" is a supported type such as "integer", "bit", "character", "real", etc.
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
EIF_REFERENCE_FUNCTION eif_reference_function (char * name, int * tid);
EIF_INTEGER_FUNCTION eif_integer_function (char * name, int * tid);
EIF_CHARACTER_FUNCTION eif_character_function (char * name, int * tid);
EIF_REAL_FUNCTION eif_real_function (char * name, int * tid);
EIF_DOUBLE_FUNCTION eif_double_function (char * name, int * tid);
EIF_BOOLEAN_FUNCTION eif_boolean_function (char * name, int * tid);
EIF_POINTER_FUNCTION eif_pointer_function (char * name, int * tid);
EIF_BIT_FUNCTION eif_bit_function (char * name, int * tid);
</code>
==Description==
These functions return the address of the Eiffel function of name <code lang="text">name</code> from the class, which type identifier is <code lang="text">tid</code>.
{| border="1"
! Use this function !! For an Eiffel function returning
|-
| eif_reference_function
| Eiffel reference
|-
| eif_integer_function
| Eiffel integer
|-
| eif_character_function
| Eiffel character
|-
| eif_real_function
| Eiffel real
|-
| eif_double_function
| Eiffel double
|-
| eif_boolean_function
| Eiffel boolean
|-
| eif_pointer_function
| Eiffel pointer
|-
| eif_bit_function
| Eiffel bit
|}
If the visible exception is enabled, it raises an visible exception upon failure.
==Return value==
Successful: The address of the function.
Failing: NULL (function does not exist or is not visible).
==Notes==
The Eiffel function cannot be a C external. In this case, you must directly call the C routine.
The return value is an address: to use it as a routine, you must call it with arguments or at least with ().
No argument type checking is done. You may cast the address of an Eiffel routine, obtained with these functions, when calling it with real arguments.
If the function returns an Eiffel reference, you must protect it with [[eif_protect]].
==Conformance==
ISE Eiffel 4.4 and later.
==Compatibility==
Compatibility with deprecated functions is shown in this table.
{| border="1"
! Function name !! Equivalent deprecated function name
|-
| eif_reference_function
| eif_fn_ref
|-
| eif_integer_function
| eif_fn_int
|-
| eif_real_function
| eif_fn_float
|-
| eif_double_function
| eif_fn_double
|-
| eif_character_function
| eif_fn_char
|-
| eif_bit_function
| eif_fn_bit
|-
| eif_boolean_function
| eif_fn_bool
|-
| eif_pointer_function
| eif_fn_pointer
|}
{{SeeAlso| <br/>
[[eif_type_id]]<br/>
[[eif_protect]]<br/>
[[eif_procedure]] }}

View File

@@ -0,0 +1,35 @@
[[Property:title|eif_name_by_tid]]
[[Property:weight|-1]]
[[Property:uuid|7ae34f4d-5eaf-0703-29f7-54dc4f0fd49d]]
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
char *eif_name_by_tid (EIF_TYPE_ID tid);
</code>
==Description==
The <code lang="text">eif_name_by_tid</code> function returns the name of the class corresponding to <code lang="text">tid</code>.
==Return value==
A statically allocated C string which is the name of the class. If <code lang="text">tid</code> is invalid, it returns <code lang="text">NULL</code>.
==Conformance==
ISE Eiffel 4.4 and later.
==Compatibility==
[[eif_name_by_tid]] is equivalent to [[eif_name]].
{{SeeAlso| <br/>
[[eif_type]] <br/>
[[eif_type_by_reference]] <br/>
[[eif_type_id]] }}

View File

@@ -0,0 +1,35 @@
[[Property:title|eif_name]]
[[Property:weight|-2]]
[[Property:uuid|2921b2ef-1f59-cd26-df50-5cb946eae84c]]
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
char *eif_name (EIF_TYPE_ID tid);
</code>
==Description==
The <code lang="text">eif_name</code> function returns the name of the class corresponding to <code lang="text">tid</code>.
==Return value==
A statically allocated C string which is the name of the class. If <code lang="text">tid</code> is invalid, it returns <code lang="text">NULL</code>.
==Conformance==
ISE Eiffel 4.4 and later.
==Compatibility==
[[eif_name]] is equivalent to [[eif_name_by_tid]].
{{SeeAlso| <br/>
[[eif_type]] <br/>
[[eif_type_by_reference]] <br/>
[[eif_type_id]] }}

View File

@@ -0,0 +1,47 @@
[[Property:title|eif_procedure]]
[[Property:weight|1]]
[[Property:uuid|3937f124-fffa-3244-d2e4-46ccfcec5fa8]]
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
EIF_PROCEDURE eif_procedure (char * name, int * tid);
</code>
==Description==
The <code lang="text">eif_procedure</code> function returns the address of the Eiffel procedure of name <code lang="text">name</code> from the class, which type identifier is <code lang="text">tid</code>.
If the visible exception is enabled, it raises an visible exception upon failure.
==Return value==
Successful: Address of the procedure.
Failing: <code lang="text">NULL</code>. (The procedure does not exist or is not visible).
Otherwise, the address of the procedure is returned.
==Notes==
The Eiffel procedure cannot be a C external. In this case, you must directly call the C routine.
The return value is an address: to use it as a routine, you must call it with arguments or at least with ().
No argument type checking is done. You may cast the address of an Eiffel routine obtained with <code lang="text">eif_procedure</code> when calling it with real arguments.
==Conformance==
ISE Eiffel 4.4 and later.
==Compatibility==
<code lang="text">eif_procedure</code> is equivalent to <code lang="text">eif_proc</code>, which is deprecated.
{{SeeAlso| <br/>
[[eif_type_id]] <br/>
[[eif_*_function]] }}

View File

@@ -0,0 +1,36 @@
[[Property:title|eif_protect]]
[[Property:weight|2]]
[[Property:uuid|f335a229-93c4-4f3f-6fca-9c4c190745c4]]
==Synopsis==
<code lang="text">
#include "eif_hector.h"
EIF_OBJECT eif_protect (EIF_REFERENCE ref);
</code>
==Description==
The <code lang="text">eif_protect</code> function protects the Eiffel reference <code lang="text">ref</code> from the garbage collector. It keeps a reference on it so that the garbage collector does not collect it if it is not referenced from Eiffel any longer.
==Return value==
The <code lang="text">eif_protect</code> function returns an <code lang="text">EIF_OBJECT</code>. This <code lang="text">EIF_OBJECT</code> can be used later on to access <code lang="text">ref</code> with [[eif_access]].
==Conformance==
ISE Eiffel 4.4 and later.
==Compatibility==
<code lang="text">eif_protect</code> is equivalent to <code lang="text">henter</code>, which is deprecated.
{{SeeAlso| <br/>
[[eif_access]] <br/>
[[eif_adopt]] <br/>
[[eif_wean]] }}

View File

@@ -0,0 +1,37 @@
[[Property:title|eif_string]]
[[Property:weight|5]]
[[Property:uuid|d203c941-df82-495a-55f3-791652b0e9ef]]
==Synopsis==
<code lang="text">
#include "eif_plug.h"
EIF_REFERENCE eif_string (char * string);
</code>
==Description==
The <code lang="text">eif_string</code> macro returns an Eiffel string corresponding to the C string <code lang="text">string</code>.
The return value does not reference <code lang="text">string</code>.
==Notes==
This function return an Eiffel reference, which must be protected with [[eif_protect]].
==Conformance==
ISE Eiffel 4.5 and later.
==Compatibility==
<code lang="text">eif_string</code> is equivalent to <code lang="text">RTMS</code>, which is deprecated.
{{SeeAlso| <br/>
[[eif_protect]]<br/>
[[eif_create]] }}

View File

@@ -0,0 +1,45 @@
[[Property:title|eif_type_id]]
[[Property:weight|9]]
[[Property:uuid|248182c3-5e89-4adc-097f-f03cb934eb63]]
==Synopsis==
<code lang="text">
#include "eif_gen_conf.h"
EIF_TYPE_ID eif_type_id (char * type);
</code>
==Description==
The <code lang="text">eif_type_id</code> function returns the type identifier corresponding to <code lang="text">type</code>, which is the name of the type.
==Return value==
The type identifier of <code lang="text">type</code>.
==Notes==
An error cannot be caught by a visible exception.
The type is not necessary visible.
==Conformance==
ISE Eiffel 4.3 and later.
==Compatibility==
<code lang="text">eif_type_id</code> is equivalent to [[eif_type_by_name]].
With ISE Eiffel 4.2 and earlier, use <code lang="text">eif_generic_type</code> for generic types.
{{SeeAlso| <br/>
[[eif_*_function]] <br/>
[[eif_procedure]] <br/>
[[eif_type]] <br/>
[[eif_name]] }}

View File

@@ -0,0 +1,43 @@
[[Property:title|eif_type_by_name]]
[[Property:weight|7]]
[[Property:uuid|51549b56-757c-f91f-6d27-5784a12181ac]]
==Synopsis==
<code lang="text">
#include "eif_gen_conf.h"
EIF_TYPE_ID eif_type_by_name (char * type);
</code>
==Description==
The <code lang="text">eif_type_by_name</code> function returns the type identifier corresponding to <code lang="text">type</code>, which is the name of the type.
==Return value==
The <code lang="text">eif_type_by_name</code> function returns the type.
==Notes==
An error cannot be caught by a visible exception.
The type is not necessary visible.
==Conformance==
ISE Eiffel 4.3 and later.
==Compatibility==
<code lang="text">eif_type_by_name</code> is equivalent to [[eif_type_id]].
{{SeeAlso| <br/>
[[eif_*_function]] <br/>
[[eif_procedure]]<br/>
[[eif_type]] <br/>
[[eif_name]] }}

View File

@@ -0,0 +1,33 @@
[[Property:title|eif_type_by_reference]]
[[Property:weight|8]]
[[Property:uuid|1258584a-0aae-3246-0553-98817deda6e0]]
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
EIF_TYPE_ID eif_type_by_reference (EIF_REFERENCE reference);
</code>
==Description==
The <code lang="text">eif_type_by_reference</code> function returns the type identifier corresponding to <code lang="text">reference</code>.
==Return value==
Type identifier of <code lang="text">reference</code>.
The behavior is unpredictable if <code lang="text">reference</code> is not a valid Eiffel reference.
==Conformance==
ISE Eiffel 4.5 and later.
{{SeeAlso| <br/>
[[eif_type]] <br/>
[[eif_name]] <br/>
[[eif_type_id]] }}

View File

@@ -0,0 +1,35 @@
[[Property:title|eif_type]]
[[Property:weight|6]]
[[Property:uuid|8c200b03-cae1-bbcd-98b0-1767402744be]]
==Synopsis==
<code lang="text">
#include "eif_cecil.h"
EIF_TYPE_ID eif_type (EIF_OBJECT object);
</code>
==Description==
The <code lang="text">eif_type</code> function returns the type identifier corresponding to <code lang="text">object</code>.
==Return value==
Type identifier of <code lang="text">object</code>. The behavior is unpredictable if <code lang="text">object</code> is not a valid Eiffel object.
==Conformance==
ISE Eiffel 4.3 and later.
==Compatibility==
<code lang="text">eif_type(object)</code> is equivalent to <code lang="text">eif_type_by_reference(eif_access(object))</code>.
{{SeeAlso| <br/>
[[eif_type_by_reference]] <br/>
[[eif_type_id]] }}

View File

@@ -0,0 +1,32 @@
[[Property:title|eif_wean]]
[[Property:weight|10]]
[[Property:uuid|d94fdbce-8cbd-7714-ebfc-38e1f0526eaa]]
==Synopsis==
<code lang="text">
#include "eif_hector.h"
EIF_REFERENCE eif_wean (EIF_OBJECT obj);
</code>
==Description==
The <code lang="text">eif_wean</code> function releases the protection of the Eiffel reference, which is protected by the Eiffel object <code lang="text">obj</code>.
==Return value==
The Eiffel reference previously protected by <code lang="text">obj</code>.
==Conformance==
ISE Eiffel 4.1 and later.
{{SeeAlso| <br/>
[[eif_access]] <br/>
[[eif_adopt]] <br/>
[[eif_protect]] }}

View File

@@ -0,0 +1,5 @@
[[Property:title|CECIL Reference]]
[[Property:weight|4]]
[[Property:uuid|20ca6ef1-0d26-a556-955c-96bed93dfdfb]]
References for CECIL features

View File

@@ -0,0 +1,76 @@
[[Property:title|CECIL - Basic sample]]
[[Property:weight|2]]
[[Property:uuid|ed699d37-f480-0cef-817f-9f4a857c1691]]
==cecil-test==
After you have done the appropriate steps to compile the example, you will get a `cecil.exe` on windows, or `cecil` on Unix.
This example performs some basic tests of CECIL from C to Eiffel and Eiffel to C. You can:
* choose to raise an exception when a routine is not visible
* create an Eiffel string
* choose to raise a precondition violation from C.
A typical output will be:
<code>
$ cecil
Do you want to enable the visible exception? (y-yes, n-no):n
Disable visible exception
====== In eiffel_call ======
Eiffel type id = 9
Eiffel procedure make 0x100546b4
Eiffel object = 0x30068030
Testing linked_list...
12345
test_linked_list OK
Testing memory...
Give string length (enter a high number for raising an Eiffel exception)
234
Memory OK
Testing if string void ...
Enter a string: (press enter if you want to raise an Eiffel exception)
wefsd
wefsdTesting precondition...By default it is true
====== Done ======
====== In eiffel_call ======
Eiffel type id = 9
Eiffel procedure test_linked_list 0x10054ebc
Eiffel object = 0x30068030
Testing linked_list...
12345
test_linked_list OK
====== Done ======
====== In eiffel_call_1_arg ======
Eiffel type id = 9
Eiffel procedure print 0x1004e0a8
Eiffel object = 0x30068030
Eiffel object = 0x30068030
Execute the Eiffel code `print (linked_list)' from the C side:
MAIN [0x30068030]
linked_list: LINKED_LIST [0x30068C40]
====== Done ======
====== In cecil_test ======
protected indirection of 30068c40 is 300311bc
Eiffel type id of STRING = 198
Eiffel type id of LINKED_LIST [STRING] = 224
Linked List forth: 10222fbc
Linked list object = 0x30068c40
Do you want to test the visibility of an Eiffel routine? (y-yes, n-no):
n
Do you want raise a precondition violation? (y-yes, n-no):
n
====== Done ======
</code>

View File

@@ -0,0 +1,46 @@
[[Property:title|CECIL - C to Eiffel]]
[[Property:weight|0]]
[[Property:uuid|c3b64ef2-28b2-920e-44fb-4cff2320c099]]
==array==
This example shows how to create an Eiffel array from an existing C array. After you have done the appropriate steps to compile the example, you will get a `cecil.exe` on windows, or `cecil` on Unix. Launch the program and you will be prompted for 10 integers that will be inserted in a C array, it will then initialize the Eiffel array and calls display from the MY_ARRAY class. A typical output will be:
<code>
$ ./cecil
Enter 10 integers:
Enter element 1: 1
Enter element 2: 2
Enter element 3: 3
Enter element 4: 4
Enter element 5: 5
Enter element 6: 6
Enter element 7: 7
Enter element 8: 8
Enter element 9: 9
Enter element 10: 10
Display an Eiffel Array:
@1 = 1
@2 = 2
@3 = 3
@4 = 4
@5 = 5
@6 = 6
@7 = 7
@8 = 8
@9 = 9
@10 = 10
</code>
==string==
This example shows how to create an Eiffel string from an existing C string. After you have done the appropriate steps to compile the example, you will get a `cecil.exe` on windows, or `cecil` on Unix. Launch the program and you will be prompted for a string, it will then initialize the Eiffel string and calls io. put_string from the STD_FILES class. A typical output will be:
<code>
$ ./cecil
Enter a string to convert in Eiffel string:
Hello World!
Now printing the Eiffel string from Eiffel
Hello World!
</code>

View File

@@ -0,0 +1,96 @@
[[Property:title|CECIL - Eiffel to C]]
[[Property:weight|1]]
[[Property:uuid|3d1df3fe-2ac8-1ba3-c846-8329ea8a3772]]
==array==
This example shows how to create a C array from an existing Eiffel array.
After you have done the appropriate steps to compile the example, you will get a `cecil.exe` on windows, or `cecil` on Unix.
Launch the program and you will be prompted for 10 integers that will be inserted in an Eiffel array, it will then initialize the C array and display it.
A typical output will be:
<code>
$ ./cecil
This example create n array on the Eiffel side and print it on the C side
Enter 10 integers:
1
2
3
4
5
6
7
8
9
10
Displaying from C
@1 = 1
@2 = 2
@3 = 3
@4 = 4
@5 = 5
@6 = 6
@7 = 7
@8 = 8
@9 = 9
@10 = 10
</code>
==object==
This example shows the Eiffel memory management and all issues when passing an Eiffel object reference to C. In the example, you can edit the file `root_class.e` to modify the example:
<code>
--give_to_c (o1)
give_to_c_by_pointer ($o1) -- Choose the way you pass it
</code>
When you choose the first possibility (commented by default), give_to_c will use the CECIL API eif_adopt to keep a reference on the Eiffel object. When you choose the second possibility, give_to_c_by_pointer will use the CECIL API eif_protect to keep a reference on the Eiffel object. Until forget_from_c is called from the C side, the object o1 will not be collected since we have protected it through the call to give_to_c or give_to_c_by_pointer. At the end after the object o1 is collected, we try to perform an operation on it which will fail with a call on void target exception. A typical output will be:
<code>
$ cecil
Creating o1
Object string is o1
Give it to C
Losing reference to initial o1 from Eiffel
Collecting...
Display new o1:
Object string is o2
Display o1 given to C:
Object string is o1
Losing reference from C
Losing reference from Eiffel
Collecting...
An Eiffel object of type OBJECT is collected
Old o1 forgot from both C and Eiffel:
Raise a Void exception..
cecil: system execution failed.
Following is the set of recorded exceptions:
-------------------------------------------------------------------------------
Class / Object Routine Nature of exception Effect
-------------------------------------------------------------------------------
ROOT_CLASS make @26 display:
<30068030> Feature call on void target. Fail
-------------------------------------------------------------------------------
ROOT_CLASS make @26
<30068030> Routine failure. Fail
-------------------------------------------------------------------------------
ROOT_CLASS root's creation
<30068030> Routine failure. Exit
-------------------------------------------------------------------------------
An Eiffel object of type OBJECT is collected
</code>
==string==
This example shows how to create a C string from an existing Eiffel string. After you have done the appropriate steps to compile the example, you will get a `cecil.exe` on windows, or `cecil` on Unix. Launch the program and you will be prompted for a string from Eiffel and a C string will be created and display. A typical output will be:
<code>
$ cecil
Enter a string to convert into a C string:
Hello World!
Here is the C string:
Hello World!
</code>

View File

@@ -0,0 +1,41 @@
[[Property:title|CECIL - How to compile the samples?]]
[[Property:weight|4]]
[[Property:uuid|3548e1b4-9488-10d5-561e-f817c15d6ff0]]
==Compiling for Windows==
Depending on your C compiler different steps have to be done, but do not forget to do the following before starting the C compiler specific part in a DOS console:
<code>set ISE_EIFFEL=XXX</code>
where XXX is the EiffelStudio installation directory.
===With Borland C++:===
By default, Borland C++ is not in your path, so you will have to first set your path correctly by typing:
<code>set PATH=%ISE_EIFFEL%\BCC55\bin;%PATH%</code>
If the file `Makefile. win' is present, then you can launch the compilation with:
<code>make -f Makefile. win</code>
Otherwise launch the compilation with:
<code>make -f Makefile. bcb</code>
===With Microsoft Visual C++:===
By default, the command line tools of Visual C++ should be available from the command line.
If the file `Makefile. win' is present, then you can launch the compilation with:
<code>nmake -f Makefile. win</code>
Otherwise launch the compilation with:
<code>nmake -f Makefile. msc</code>
==Compiling for UNIX==
Then, make sure that your path to the EiffelStudio executables are properly configured before launching the command below.
To compile and execute from scratch type:
<code>finish_freezing -library</code>

View File

@@ -0,0 +1,70 @@
[[Property:title|CECIL - Threads]]
[[Property:weight|3]]
[[Property:uuid|44f2ee31-8634-6e54-f45a-8b36f780f888]]
==bank_account==
After you have done the appropriate steps to compile the example, you will get a `bank_account.exe` on windows, or `bank_account` on Unix.
This program launches two types of threads:
* the spenders withdraw some money from a shared bank account
* the savers make some deposits on it.
The Eiffel Threads are launched from C. The synchronization is done from Eiffel. The shared bank account is a C structure, and is updated by the Eiffel Threads using some C externals.
<br/>
In main. c: <br/>
LISTSZ size of bank account history. <br/>
DEPOSITORS numbers of savers. <br/>
WITHDRAWERS numbers of spenders.
<br/>
A typical output will be:
<code>
$ bank_account
**** Bank account report:
Thread 0x30036350 DEPOSIT 161
Thread 0x30036350 DEPOSIT 614
Thread 0x30036350 DEPOSIT 626
Thread 0x30036350 DEPOSIT 880
Thread 0x30036350 DEPOSIT 601
Thread 0x30036350 DEPOSIT 480
Thread 0x30036350 DEPOSIT 177
Thread 0x30036350 DEPOSIT 451
Thread 0x30036350 DEPOSIT 96
Thread 0x30036350 DEPOSIT 219
*** BALANCE: 5305
Do you want to continue? (y/n)
y
**** Bank account report:
Thread 0x3003fcf0 DEPOSIT 161
Thread 0x3004f088 DEPOSIT 161
Thread 0x300567a0 WITHDRAWAL 161
Thread 0x3005e1f0 WITHDRAWAL 161
Thread 0x30036350 DEPOSIT 531
Thread 0x3003fcf0 DEPOSIT 614
Thread 0x3004f088 DEPOSIT 614
Thread 0x300567a0 WITHDRAWAL 614
Thread 0x30036350 DEPOSIT 409
Thread 0x3003fcf0 DEPOSIT 626
*** BALANCE: 7485
Do you want to continue? (y/n)
y
**** Bank account report:
Thread 0x3004f088 DEPOSIT 626
Thread 0x30036350 DEPOSIT 799
Thread 0x300567a0 WITHDRAWAL 626
Thread 0x3005e1f0 WITHDRAWAL 614
Thread 0x3003fcf0 DEPOSIT 880
Thread 0x30036350 DEPOSIT 860
Thread 0x3004f088 DEPOSIT 880
Thread 0x300567a0 WITHDRAWAL 880
Thread 0x30036350 DEPOSIT 307
Thread 0x3004f088 DEPOSIT 601
*** BALANCE: 10318
</code>

View File

@@ -0,0 +1,14 @@
[[Property:title|CECIL samples]]
[[Property:weight|5]]
[[Property:uuid|dab15073-3970-7e47-a2d8-c926faa50ade]]
Before trying the examples, please take a moment and look at the [[CECIL - How to compile the samples?|description]] that will explain how to compile the CECIL samples.
Available samples include:
* [[CECIL - C to Eiffel|C to Eiffel]]
* [[CECIL - Eiffel to C|Eiffel to C]]
* [[CECIL - Basic sample|Basic CECIL sample]]
* [[CECIL - Threads|Threads]]

View File

@@ -0,0 +1,35 @@
[[Property:title|Compiling an Eiffel system for CECIL]]
[[Property:weight|1]]
[[Property:uuid|94a549df-1919-9dcd-82b3-1cd82e064a03]]
==Compiling your Eiffel system for CECIL==
It is very simple to "Cecilize" your Eiffel system, that is to say make its features available from the outside through CECIL. You will compile it as you normally would - either freeze it or finalize it. The only supplementary precaution is to make the features and classes that will be used by CECIL [[Group Options|visible]].
==Building a CECIL archive==
The EiffelStudio compiler produces both C code and a "Makefile". The Makefile compiles and links that C code in a subdirectory one level below the EIFGENs directory of a project. For frozen/melted code, the Makefile is located in the W_code subdirectory. For finalized code, it is in the F_code subdirectory.
To produce a CECIL library, you must: open a shell (unix) or the MS-DOS prompt (Windows), go to the subdirectory that contains the Makefile, and then type:
<code> make cecil </code> (on unix and on windows with Borland)
<code> nmake cecil </code> (on windows with VC++)
This generates a CECIL archive whose name derived from the name system name of the Eiffel system, as follows:
<code> lib<system name>.a </code> (on unix)
<code> lib<system name>.lib </code> (on Windows)
For example, the corresponding archive for an Eiffel system called "test", would be called either "libtest.a" (Unix) or "libtest.lib" (Windows).
Note that through CECIL you can use an Eiffel system compiled in any of the Eiffel compilation modes:
* Finalized C code.
* Workbench (melted/frozen) code, usually for development purposes. In this case you must copy the ''<system name>.melted'' file ( where ''<system name>'' is the name of your system) located in EIFGENs\<target_name>\W_code to the directory where you intend to execute your C application from.
{{note|each time you melt the Eiffel system, the ''<system name>. melted'' file is updated. }}
{{caution|In the second case (workbench mode), it is not possible to call through the CECIL interface any routine that has been melted in the last compilation; this would raise the run-time exception: <br/>
''' $ applied to melted routine''' <br/>
The solution is simply to refreeze the system. }}

View File

@@ -0,0 +1,19 @@
[[Property:title|CECIL]]
[[Property:weight|3]]
[[Property:uuid|c03112b8-578e-cc1a-ee13-c6928b787529]]
This document provides an overview of the C-Eiffel Call-In Library (CECIL) as defined in Eiffel: The Language (ETL). The first section addresses how to compile and run a CECIL program, on the [[Compiling an Eiffel system for CECIL|Eiffel side]] and on the [[Using a CECIL archive|C side]] . The [[CECIL interface overview|second part]] contains a more precise description of the Eiffel types, the protection mechanism as well as how to write and use C externals.
CECIL, designed by Eiffel Software , is the C library that permits C and C++ applications (as well as applications written in other languages) to take advantage of almost all Eiffel facilities: create Eiffel objects, apply features to them. The basics of CECIL are described in chapter 24 of the reference book on Eiffel, Eiffel: The Language, which covers interfaces between Eiffel and other languages. Important material can also be found in the Eiffel Software manual Eiffel: The Environment.
The CECIL documentation, man pages and examples are part of the standard delivery of EiffelStudio 5.0 and higher.
The present document complements the descriptions of Eiffel: The Language. Note that CECIL has been revised and improved since that book was published, so the explanations below have precedence over those in the book.
This document is intended for both Windows and Unix users. Only a few of the sections, clearly marked, are platform-specific.
To access Eiffel mechanisms from C or other external languages:
* Compile your Eiffel system so as to generate "Cecilized" code, that is to say code callable from the outside. See [[Compiling an Eiffel system for CECIL|Compiling your Eiffel system for CECIL]] .
* In writing the external code that will use the facilities of the Eiffel system, use the CECIL functions as specified in chapter 24 of ''Eiffel: The Language''. See also [[CECIL interface overview|The CECIL interface overview]] .
* C-compile and link that code. See [[Using a CECIL archive|Building a C system using CECIL]] .
For feature by feature specification, please have a look at [[CECIL Reference|the man pages]] .

View File

@@ -0,0 +1,97 @@
[[Property:title|Using a CECIL archive]]
[[Property:weight|2]]
[[Property:uuid|e8438c9b-65ae-368f-6559-a0d5b28db4b7]]
==Linking the CECIL archive into a program==
The CECIL archive already incorporates the Eiffel run-time. To use the functions provided in the CECIL archive, simply write the C programs according to the CECIL specifications of ETL, and then include the CECIL archive in the link line of your C application.
On Unix/linux, this line looks like this:
<code>ld -o [name of your CECIL executable] [your C object files and archives]lib<system name>.a -lm</code>
{{note|On Unix, linking with "-lm" is required since the Eiffel run-time uses the standard math libraries. You may need to link with other libraries (for example, on linux: with "-lbsd", in MT mode with "-lpthread" (posix threads) or "-lthread" (solaris)). }}
on Windows, with MS VC++:
<code>link [your link flags] -OUT:[name of your cecil executable] [your C object files and archives] lib<system name>.lib [other Windows libraries]</code>
on Windows with Borland:
<code>ilink32 -ap -c -Tpe main.obj c0w32.obj, [name of your cecil executable],,EIFGENs\target_name\W_code\lib<system name>.lib CW32 IMPORT32 OLE2w32,,</code>
===Notes for compiling CECIL C files:===
The CECIL library is built automatically, which is unfortunately not the case of the corresponding object files of the cecil program you wrote. <br/>
The C flags to use are usually the same as the ones needed during the compilation of the generated C-code plus those which are relevant to your own C-code.
Typically, you will compile with your flags as below (if you are using gcc):
<code>gcc -c -O -I$ISE_EIFFEL/studio/spec/$PLATFORM/include -I<SOME_INCLUDE_PATH> -D<SOME_FLAGS> your_file.c</code>
or , if you are on Windows using MS VC++:
<code>cl -c -nologo -Ox -I$ISE_EIFFEL\studio\spec\windows\include -I<SOME_INCLUDE_PATH> -D<SOME_FLAGS> your_file.c</code>
or, if you are on Windows using Borland:
<code>bcc32 -c -I$ISE_EIFFEL\studio\spec\windows\include -I<SOME_INCLUDE_PATH> -D<SOME_FLAGS> your_file.c</code>
{{note|if you want to use the multithreaded facilities of Eiffel, you should define the EIFFEL MT flags by adding "-DEIF_THREADS" to the command line and follow the instructions of your C compiler and platform to find out which additional flags you may need. For example, on Solaris you need to add "-DSOLARIS_THREADS -D_REENTRANT". }}
You can specify a Makefile in your configuration file, so that your C files will be compiled automatically after the Eiffel compilation and before the final linking. See [[Externals Options|the manipulation of external]] in the project settings to add <code>$PATH_TO_MAKEFILE/your_makefile</code>.
This makefile will be run from the $/EIFGENs/target_name/W_code or $/EIFGENs/target_name/F_code directory. You should not give the CECIL executable the same name as your system, because it will be replaced by the Eiffel executable when you run another compilation.
==Initializing the Eiffel run-time==
Even though the main thread of control resides in the "C side" of the program, the Eiffel run-time must be initialized correctly before it can use CECIL facilities to communicate with the Eiffel world.
In the C file containing the "main" C function, you must add the following line to include the header file "eif_setup. h" provided with this example:
<code lang="c">
#include "eif_setup.h" /* Macros EIF_INITIALIZE and EIF_DISPOSE_ALL */
#include "eif_eiffel.h" /* Exported functions of the Eiffel run-time */</code>
Your "main" function must have the three standard arguments of the C "main" function: "argc", "argv" and "envp" and include the following macros that are defined in "eif_setup. h":
<code lang="c">
int main(int argc, char **argv, char **envp)
/* Please respect this signature: 'argc', 'argv' and 'envp' are used * in EIF_INITIALIZE. */
{
/* declarations of variables */
/* Initialize the Eiffel run-time. */
EIF_INITIALIZE(failure)
/* body of your "main" function */
/* Reclaim the memory allocated by the Eiffel run-time. */
EIF_DISPOSE_ALL
}</code>
{{note|The above mentioned macros must imperatively be in the body of the "main" function for the Eiffel exception handling mechanism to work correctly. You also need to add the Eiffel run time directory to the list of directories in which the C compiler searches for include files. You can do so by using the "-I" option of your C compiler. You can only link one CECIL library into your C applications at a time. }}
{{caution|Even though external object files and archives are correctly specified in the "object" clause of the configuration file, you will need to explicitly link them to your C application. }}

View File

@@ -0,0 +1,17 @@
[[Property:title|Eiffel "external" mechanism]]
[[Property:weight|0]]
[[Property:uuid|b6ea568d-a9d3-3220-7957-d9c81620e885]]
{{UnderConstruction}}
The Eiffel mechanism for interfacing with other languages, as defined by the [[ECMA Standard 367|Eiffel standard (8.31)]] uses a syntax for '''external''' features, that is, features that are in languages or libraries external to Eiffel.
Additionally, there is a notion of such external languages being either '''registered''' or '''unregistered'''. A language is registered if every Eiffel implementation must support the external interface to this language as defined by the standard. So the names of all registered languages appear in the Eiffel standard. And the details of the specific external mechanisms for those languages also appear in the standard. Registered languages included in the June 2006 edition of the standard are '''"C"''', '''"C++"''', and '''"dll"'''.
The case of unregistered languages is simply that there is no guarantee that such a language is supported by any particular Eiffel compiler. So, a the name of an unregistered language might appear as '''"Cobol"''' or '''"Ada"'''. These names may be meaningful to particular Eiffel compilers, but from the standpoint of the standard they are arbitrary manifest strings.

View File

@@ -0,0 +1,132 @@
[[Property:modification_date|Mon, 03 Sep 2018 08:31:04 GMT]]
[[Property:publication_date|Mon, 03 Sep 2018 08:28:15 GMT]]
[[Property:title|Interfacing with C and C++]]
[[Property:weight|0]]
[[Property:uuid|dcc4e216-307b-46ec-1bc1-a15da8b99469]]
{{UnderConstruction}}
Interfacing with C and C++ are similar enough that both can be covered together. There are two basic mechanisms available. The first and simpler of the two uses an existing routine and is available only to C externals. Using this approach you simply specify the '''signature''' of an existing C function along with where the function can be found. The second mechanism allows you to write C or C++ code inline. The second option is always recognizable by the presence of the word "'''inline'''" in the external specification. Again, the '''inline''' option is the only one allowed for C++ externals.
==Using an existing C function==
Here is an example of an external targeting an existing C function. In this case it's the <code>floor</code> function from the C library.
<code>
floor (v: DOUBLE): DOUBLE
-- Floor of `v'
external
"C signature (double): double use <math.h>"
end
</code>
The Eiffel external function <code>floor</code> now gives Eiffel code access to the C library function of the same name.
Here <code>external</code> is an Eiffel keyword that introduces the external specification that appears in the quoted string that follows. (The quoted string is actually an Eiffel [[ET: Other mechanisms|manifest string]], so it could actually be a simple quoted string or a [[ET: Other mechanisms|verbatim string]].) Within the quoted string we find first the registered language designator, in this case "C", followed by the function's signature, followed by the location in which the C function can be found. The terms "signature" and "use" within the quoted string are technically not Eiffel language keywords, but are keywords used in the specification of externals. There is one other similar keyword "inline" which can be used, but we will address it later.
The "signature" consists of the types of the arguments to C function as well as the function's return type. The argument types are separated by commas in a list enclosed in parentheses. A colon precedes the function type. In cases in which the target function takes no arguments, it is not necessary to include a set of empty parentheses in the signature. However, for compatibility purposes, the empty parentheses are allowed.
The "use" part denotes provides a file name or list of file names. File names can be either "user" file names or "system" file names. In the case of our example, a system file name "<code><math.h></code>" is used. System files are those that should be found by the system with no additional information. System file names are enclosed in angle brackets. User file names are included in a quoted string. User file names will be passed as written to the operating system. Remember that when coding a user file name, that because it already occurs within a quoted string, you must use the percent sign to code the quotation marks inside a quoted string, for example:
<code>
"C signature (double): double use %"my_c_header.h%""
</code>
Alternatively, you could code the external as a verbatim string. This would make the percent signs unnecessary.
There's one more thing to note about using existing C functions. In the <code>floor</code> example above, the Eiffel function has the same name as the C function it targets. But that may not always be the case. It's possible that the C function name might conflict with a name already established in your class, or might conflict with Eiffel naming conventions. Suppose you wanted to call the Eiffel routine <code>my_floor</code> instead of <code>floor</code>. You could use the <code>alias</code> part of the external specification to state that the actual C function name differs from the Eiffel name, as shown below.
<code>
my_floor (v: DOUBLE): DOUBLE
-- Floor of `v'
external
"C signature (double): double use <math.h>"
alias
"floor"
end
</code>
==Inline externals==
In addition to using an existing C function, you can, for both C and C++, create an '''inline''' external. The idea here is that you write the necessary C or C++ language within the definition of the external. In the case of inline externals the <code>alias</code> part is used to contain the inline code rather than a function name. Your inline C and C++ code can access the arguments of the external feature. Let's look at <code>my_floor</code> written as an inline external:
<code>
my_floor (v: DOUBLE): DOUBLE
-- Floor of `v'
external
"C inline use <math.h>"
alias
"return floor($v)"
end
</code>
In the <code>alias</code> part you see a line of C code calling the library function <code>floor</code> and returning the result. The argument to the call to <code>floor</code> needs to be the argument to the Eiffel function <code>my_floor</code>. To do this in the inline C code, the dollar sign ('$') precedes the argument name "v". So, the convention in inline externals is to use the dollar sign in C or C++ code to reference an argument of the Eiffel function.
The example below is a C++ example that involves more complex processing in the <code>alias</code> part.
<code>
c_height (a_framework: POINTER): INTEGER
-- Get ribbon height
require
a_framework_exists: a_framework /= default_pointer
external
"C++ inline use <common.h>"
alias
"{
UINT32 val;
HRESULT hr = S_OK;
IUIRibbon* pRibbon = NULL;
if (SUCCEEDED(((IUIFramework *) $a_framework)->GetView(0, IID_IUIRIBBON, (void **) &pRibbon))) {
hr = pRibbon->GetHeight(&val);
pRibbon->Release();
}
return (EIF_INTEGER) val;
}"
end
</code>
==Rules for C and C++ externals==
===C external validity===
A C external is valid if it satisfies the following conditions:
# It specifies either an external signature or an inline routine.
# If it specifies an inline routine, then
## The C text of the routine follows the <code>alias</code> keyword.
## For any occurrence, within the C text, of an identifier following a dollar sign ('$'), the identifier must be the name of an argument of the external routine.
===C++ external validity===
A C++ external is valid if it satisfies the following conditions:
# It specifies an inline routine with the C++ text of the routine occurring after the <code>alias</code> keyword.
# For any occurrence, within the C++ text, of an identifier following a dollar sign ('$'), the identifier must be the name of an argument of the external routine.
===External file name validity===
An external file name appearing after the "use" is valid if it satisfies the following conditions:
# It denotes a file when interpreted according to the conventions of the underlying operating system.
# The file is accessible for reading.
# The file contains content valid in the target language.
The first condition means that user file names must conform to the path and file names of the target environment. Such file names will be passed on to the operating system as they appear. And for system file names, those enclosed in angle brackets, this means that they must be found where the operating system would expect such system files to reside.
Some parts of the validity of external file names may not be able to be determined by an Eiffel compiler and thus ultimately depend upon the evaluation of an external compiler. For example, the Eiffel compiler might not be able to determine whether a particular C file contains valid content.
==Related pages or articles==
{{seealso| <br/>
- [https://www.eiffel.org/doc/solutions/Eiffel_%22external%22_mechanism] <br/>
- [https://www.eiffel.org/article/protecting_objects] <br/>
- [https://www.eiffel.org/article/using_externals_in_multithreaded_applications] <br/>
- [https://www.eiffel.org/article/c_c_calls_and_callbacks] <br/>
}}

View File

@@ -0,0 +1,29 @@
[[Property:title|Interfacing with DLLs]]
[[Property:weight|0]]
[[Property:uuid|4ad177dd-13ec-c237-99b3-efc9851995a5]]
Using EiffelStudio, there are two different ways to call C routines exported in DLLs. This is because on the Windows platform, there are two frequently-used calling conventions for C routines found in DLLs:
* _cdecl: referred to as the standard calling convention
* __stdcall referred to as the Pascal calling convention
Calling conventions define 1) how arguments are placed on the stack, and 2) which entity (the caller, or the callee) is responsible for returning the call stack to its previous state when the routine has completed. These two methods are NOT compatible. Therefore if you have a routine in a DLL you wish to call, one of the first things to find out about it is which calling convention it expects. DLL routines that use the `_cdecl` calling convention require the use of the '''dll32''' sub-language option. For `__stdcall`, use the '''dllwin32''' sub-language option. Here is an example:
<code>
my_cdecl_routine (a: INTEGER): POINTER
-- Encapsulation of a dll function with the `_cdecl' call mechanism.
external
"C [dll32 %"my_cdecl_dll.dll%"] (int): EIF_POINTER"
end
my_stdcall_routine (a: INTEGER): POINTER
-- Encapsulation of a dll function with the `_stdcall' call mechanism.
external
"C [dllwin32 %"my_stdcall_dll.dll%"] (int): EIF_POINTER"
end
</code>
{{note|Most OS services provided by the Win32 API use the __stdcall calling convention.}}
{{warning|Getting '''dll32''' and '''dllwin32''' reversed will cause your application's call stack to be corrupted. This will cause your application to malfunction, can cause it to crash, and can potentially crash your whole system. So getting this right is crucial to smooth implementation of external DLL calls. For more information please consult your C compiler documentation.}}

View File

@@ -0,0 +1,302 @@
[[Property:title|C++ Externals]]
[[Property:weight|2]]
[[Property:uuid|e74e2661-5d7f-2f08-5279-1c24fd16a532]]
==Introduction==
Before making C++ calls in EiffelStudio, you may want to learn the basics of making [[C externals|C calls]] , since these basics are not repeated here but they might be useful for C++ users as well and are necessary to fully benefit from this document.
==Overview==
Eiffel software must interact with software written in other languages. In this document you will learn about how to incorporate C++ classes in your Eiffel software.
The C++/Eiffel interface offers the following mechanisms:
* You can create instances of C++ classes from Eiffel, using the C++ "constructor" of your choice.
* You can apply to these objects all the corresponding operations from the C++ class: executing functions ("methods"), accessing data members, executing destructors.
* On Windows, you can use the Legacy++ tool to produce an Eiffel "wrapper class" encapsulating all the features of a C++ class, so that the result will look to the rest of the Eiffel software as if it had been written in Eiffel.
The discussion concentrates on using C++ software from Eiffel. In the other direction, you can use [[CECIL|the Cecil library (C-Eiffel Call-In Library)]] .
==Syntax specification==
In the following specification, the syntax for External and External_name is retained unchanged from ''Eiffel: The Language'', where Language_name is defined simply as Manifest_string; the rest covers the additional facilities.
<code>
External == external Language_name [External_name]
Language_name ==
'"'
Basic_language_name
[Special_external_declaration]
[Signature]
[Include_files]
'"'
Basic_language_name == "C" | "C++"
Special_external_declaration == "[" Special_feature "]"
Special_feature == Special_C_feature | Special_C++_feature
Special_C_feature == -- .... See appendix E of Eiffel: The Language...
Special_C++_feature ==
Member_function_call|
Static_function_call |
Object_creation |
Object_deletion |
Data_member_access |
Member_function_call == C++_Class
C++_Class == Class_name File_name
Class_name == Identifier
Static_function_call == static C++_Class
Object_creation == new C++_Class
Object_deletion == delete C++_Class
Data_member_access == data_member C++_Class
-- The remaining elements are repeated
-- from the C interface specification (page 291 in Eiffel: The Environment).
File_name == User_file_name | System_file_name
User_file_name == '%"' Manifest string '%"'
System_file_name == "<" Manifest_string ">"
Signature == "(" Type_list ")" [Result_type]
Type_list == {Type "," ...}
Result_type == ":" Type
Include_files == "|" File_list
File_list == {File_name "," ...}
External_name == alias Manifest_string
</code>
As with the C extensions of the previous appendix, the syntax description conventions are those of ''Eiffel: The Language''. == means "is defined as". The vertical bar | separates alternative choices, such as the three possibilities for Special_feature. The brackets [...] enclose optional components; for example a Language_name is made of required quotes, a required Basic_language_name and three further components, any or all of which may be absent. The notation {Element Separator ...} means: 0 or more occurrences ("specimens") of Element separated, if more than one, by Separator.
Several of the symbols of the syntax notation, such as the brackets or the vertical bar, also appear in the language; to avoid any confusion they are given in double quotes. For example the specification for Include_files begins with "|" to indicate that an Include_files part starts with a vertical bar. Single quotes may be used instead of double quotes when one of the quoted characters is itself a double quote; for example '%"' appearing in the production for User_file_name denotes the percent character followed by the double quote character. Special words such as '''static''' in bold italics stand for themselves, unquoted.
==Available possibilities==
===Processing C++ features===
A Special_C++_feature, if present, indicates one of the following, all illustrated by examples in the next sections:
* If the special feature's declaration simply starts with a C++ class name, followed by the associated file name, it indicates that the Eiffel feature will call a C++ member function (also known as a "method") from that class. The name of the member function is by default the same as the name of the Eiffel feature; as usual, you can specify a different name through the alias clause of the external declaration.
* If the declaration starts with <code>static</code>, it indicates a call to a C++ static function.
* If the declaration starts with <code>new</code>, it indicates a call to one of the constructors in the C++ class, which will create a new instance of that class and apply to it the corresponding constructor function.
* If the declaration starts with <code>delete</code>, it indicates a call to a destructor from the C++ class. In this case the Eiffel class may inherit [[ref:libraries/base/reference/memory_chart|MEMORY]] and redefine the dispose procedure to execute the destructor operations whenever the Eiffel objects are garbage-collected.
* If the declaration starts with <code>data_member</code>, it indicates access to a data member (attribute in Eiffel terminology) from the C++ class.
The rest of the possible components are the same as in the C interface: Signature to specify types for arguments and results; possible Include file.
===Extra argument===
For a non-static C++ member function or destructor, the corresponding Eiffel feature should include an extra argument of type POINTER, at the first position. This argument represents the C++ object to which the function will be applied.
For example, a C++ function
<code>void add(int new_int);</code>
should have the Eiffel counterpart
<code>
cpp_add (obj: POINTER; new_int: INTEGER)
-- Encapsulation of member function add.
external
"C++ [IntArray %"intarray.h%"] (IntArray *, int)"
end
</code>
This scheme, however, is often inconvenient because it forces the Eiffel side to work on objects in a non-object-oriented way. (The object-oriented way treats the current object, within a class, as implicit.) A better approach, used by Legacy++, is to make a feature such as cpp_add secret, and to export a feature whose signature corresponds to that of the original C++ function, with no extra object argument; that feature will use a secret attribute object_ptr to access the object. In the example this will give the feature
<code>
add (new_int: INTEGER)
-- Encapsulation of member function add.
do
cpp_add (object_ptr, new_int)
end
</code>
where ''object_ptr'' is a secret attribute of type <eiffel>POINTER</eiffel>, initialized by the creation procedures of the class. To the Eiffel developer, <eiffel>add</eiffel> looks like a normal object-oriented feature, which takes only the expected argument. Further examples appear below. This technique only works of course when the C++ object is implicit in the context of the Eiffel class.
There is no need for an extra argument in the case of static member functions and constructors.
==Wrapping C++ classes: Legacy++==
Before taking a look at examples of the various facilities mentioned, it is useful to consider the tool that will help you, in many cases, avoid worrying about their details.
===The role of Legacy++===
Often you will want to provide an Eiffel encapsulation of all the facilities -- member functions, static functions, constructors, destructors, data members -- of a C++ class. This means producing an Eiffel class that will provide an Eiffel feature for each one of these C++ facilities, using external declarations based on the mechanisms listed in the preceding section.
Rather than writing these external declarations and the class structure manually, you can use the Legacy++ tool to produce the Eiffel class automatically from the C++ class.
===Calling Legacy++===
Legacy++ is called with an argument denoting a ''.h'' file that must contain C++ code: one or more classes and structure declarations. It will translate these declarations into Eiffel wrapper classes. Legacy++ is only available on Windows. It is located in the $ISE_EIFFEL\studio\spec\windows\bin directory, under the name legacy.exe.
The following options are available:
* '''-E''': apply the C preprocessor to the file, so that it will process #include, #define, #ifdef and other preprocessor directives. This is in fact the default, so that you do not need to specify -E explicitly (see next option).
* '''-NE''': do not apply the C preprocessor to the file.
* '''-p''' ''directories'': use ''directories'' as include path.
* '''-c''' ''compiler'': use ''compiler'' as the C++ compiler.
* '''-g''': treat the C++ code as being intended for the GNU C++ compiler.
===Result of applying Legacy++===
Running Legacy++ on a C++ file will produce the corresponding Eiffel classes. Legacy++ processes not only C++ classes but also C++ "structs"; in both cases it will generate an Eiffel class.
Legacy++ knows about default specifiers: public for structs, private for classes.
Legacy++ will generate Eiffel features for member functions (static or not).
It will also handle any constructors and destructors given in the C++ code, yielding the corresponding Eiffel creation procedures. If there is no explicit constructor, it will produce a creation procedure with no arguments and an empty body.
For any non-static member function or destructor, Legacy++ will generate a secret feature with an extra argument representing the object, as explained in the preceding section in this page. It will also produce a public feature with the same number of arguments as the C++ function, relying on a call to the secret feature, as illustrated for <eiffel>add </eiffel>and <eiffel>cpp_add</eiffel> above.
The char* type is translated into <eiffel>STRING</eiffel>. Pointer types, as well as reference types corresponding to classes and types that Legacy++ has processed, will be translated into <eiffel>POINTER</eiffel>. Other types will yield the type <eiffel>UNRESOLVED_TYPE</eiffel>.
===Legacy++ limitations===
It is up to you to supply Eiffel equivalents of all the needed types. If Legacy++ encounters the name of a C++ class or type that it does not know -- i.e. it is neither a predefined type nor a previously translated class -- it will use the Eiffel type name <eiffel>UNRESOLVED_TYPE</eiffel>. If you do not change that type in the generated class, the Eiffel compiler will produce an error (unknown class) at degree 5.
Legacy++ does not handle inline function declarations.
Legacy++ does not handle C++ templates.
Legacy++ makes no effort to understand the C++ inheritance structure.
More generally, given the differences in the semantic models of C++ and Eiffel, Legacy++ can only perform the basic Eiffel wrapping of a C++ class, rather than a full translation. You should always inspect the result and be prepared to adapt it manually.
Legacy++'s contribution is to take care of the bulk of the work, in particular the tedious and repetitive parts. The final details are left to the Eiffel software developer.
Legacy++ is only supported on the windows platform.
==Example==
Consider the following C++ class, which has an example of every kind of facility that one may wish to access from the Eiffel side:
<code lang="cpp">
class IntArray {
public:
IntArray(int size);
~IntArray();
void output();
void add(int new_int);
static char * type();
protected:
int *_integers;
};
</code>
Here is the result of applying Legacy++ to that class, which will serve as an illustration of both the C++ interface mechanisms and Legacy++:
<code>
note
description: "Eiffel encapsulation of C++ class IntArray";
date: "$Date: 2006-10-12 03:18:50 +0200 (Thu, 12 Oct 2006) $";
revision: "$Revision: 64319 $"
class
INTARRAY
inherit
MEMORY
redefine
dispose
end
create
make
feature -- Initialization
make (size: INTEGER)
-- Create Eiffel and C++ objects.
do
object_ptr := cpp_new (size)
end
feature-- Removal
dispose
-- Delete C++ object.
do
cpp_delete (object_ptr)
end
feature
output
-- Call C++ counterpart.
do
cpp_output (object_ptr)
end
add (new_int: INTEGER)
-- Call C++ counterpart.
do
cpp_add (object_ptr, new_int)
end
feature {INTARRAY}
underscore_integers: POINTER
-- Value of corresponding C++ data member.
do
Result := underscore_integers (object_ptr)
end
feature {NONE} -- Externals
cpp_new (size: INTEGER): POINTER
-- Call single constructor of C++ class.
external
"C++ [new IntArray %"INTARRAY.H%"] (EIF_INTEGER)"
end
cpp_delete (cpp_obj: POINTER)
-- Call C++ destructor on C++ object.
external
"C++ [delete IntArray %"INTARRAY.H%"] ()"
end
cpp_output (cpp_obj: POINTER)
-- Call C++ member function.
external
"C++ [IntArray %"INTARRAY.H%"] ()"
alias
"output"
end
cpp_add (cpp_obj: POINTER; new_int: INTEGER)
-- Call C++ member function.
external
"C++ [IntArray %"INTARRAY.H%"] (EIF_INTEGER)"
alias
"add"
end
cpp_underscore_integers (cpp_obj: POINTER): POINTER
-- Value of C++ data member
external
"C++ [data_member IntArray %"INTARRAY.H%"]: EIF_POINTER"
alias
"_integers"
end
feature {NONE} -- Implementation
object_ptr: POINTER
end -- class INTARRAY
</code>

View File

@@ -0,0 +1,224 @@
[[Property:title|C externals]]
[[Property:weight|1]]
[[Property:uuid|f6a5ce2d-882b-27a2-ad6e-2e4c36027528]]
==General consideration==
As Eiffel Software's technology relies heavily on the use of a C/C++ ANSI compiler, you have to be sure to always put the correct signature of an external C/C++ routine. If it was not the case, the C compilation of your system could fail. Most of the time a C compiler is more comprehensive than a C++ compiler and most type errors won't cause you any harm, but C++ compilers are not as lax as C compilers and they will mostly generate errors.
The sections concerning [[#macros|Macros]] and [[#structs|Structs]] are also available for C++ if the macro or the struct is defined in a C++ header file.
<span id="C"></span>
==C routines==
You can encapsulate routines that are defined in a C header file. We will take some examples and will show you how to write wrappers in Eiffel.
If in a header file called `my_header.h`, you have the following declaration:
<code lang="c">
/* Routine with no parameter */
extern void no_param(void);
/* Routine with one parameter */
extern void one_param(int j);
/* Routine returning a value with no parameter */
extern size_t no_param_return(void);
/* Routine returning a value with one parameter */
extern size_t one_param_return(FILE *f);</code>
Here is the corresponding Eiffel code:
<code>
c_no_param
-- Encapsulation of a C routine with no parameter.
external
"C | %"my_header.h%""
alias
"no_param"
end
c_one_param (i: INTEGER)
-- Encapsulation of a C routine with one parameter.
external
"C (int) | %"my_header.h%""
alias
"one_param"
end
c_no_param_return: INTEGER
-- Encapsulation of a C routine with no parameter
-- returning an INTEGER
external
"C (): EIF_INTEGER| %"my_header.h%""
alias
"no_param_return"
end
c_one_param_return (p: POINTER): INTEGER
-- Encapsulation of a C routine with one parameter
-- returning an INTEGER
external
"C (FILE *): EIF_INTEGER| %"my_header.h%""
alias
"one_param_return"
end</code>
<span id="macros"></span>
==Macros==
If in a header file called `my_header.h`, you have the following declaration:
<code lang="c">
/* Predefined constants */
#define ID_MENU 128
#define ID_MENU_CHARACTER 'c'
/* Access the 'i'-th element of 'a' where 'a' * is an array of EIF_INTEGER */
#define i_th(a,i)((a) + (i)*sizeof(EIF_INTEGER))</code>
Then, the corresponding Eiffel code will look like:
<code>
menu_id: INTEGER
-- `ID_MENU' C encapsulation.
external
"C [macro %"my_header.h%"] : EIF_INTEGER"
alias
"ID_MENU"
end
menu_id_character: CHARACTER
-- `ID_MENU_CHARACTER' C encapsulation.
external
"C [macro %"my_header.h%"] : EIF_CHARACTER"
alias
"ID_MENU_CHARACTER"
end
i_th (p: POINTER; i: INTEGER): INTEGER
-- Access the `i'-th element of `p', array of C EIF_INTEGER.
external
"C [macro %"my_header.h%"] (EIF_INTEGER *, EIF_INTEGER): EIF_INTEGER"
alias
"i_th"
end</code>
<span id="structs"></span>
==Structs==
The struct encapsulation enables you to wrap C/C++ structures easily without having to write any additional code in a C header file as it was the case until Eiffel Software introduced this new keyword in the external specification with the 4.5 release of the Eiffel Software environment. With the struct encapsulation you can set and retrieve the value of a certain field of a struct.
If in a header file called `my_header.h`, you have the following declaration of the `Point` structure whose `x` and `y` fields we want to access and set:
<code lang="c">
/* Definition of `Point' */
typdef struct point {
int x;
int y;
} Point;</code>
Then, the corresponding Eiffel code will look like:
<code>
x (p: POINTER): INTEGER
-- Access field x of struct pointed by `p'.
external
"C [struct %"my_header.h%"] (Point): EIF_INTEGER"
alias
"x"
end
y (p: POINTER): INTEGER
-- Access field y of struct pointed by `p'.
external
"C [struct %"my_header.h%"] (Point): EIF_INTEGER"
alias
"y"
end
set_x (p: POINTER; v: INTEGER)
-- Set field x of struct pointed by `p'.
external
"C [struct %"my_header.h%"] (Point, int)"
alias
"x"
end
set_y (p: POINTER: v: INTEGER)
-- Set field y of struct pointed by `p' with `v'.
external
"C [struct %"my_header.h%"] (Point, int)"
alias
"y"
end</code>
<span id="windows"></span>
==Windows externals==
===DLLs===
With EiffelStudio you now have two different ways to call C routines exported in a DLL. Why two, because Windows provides two ways to call a C routine in a DLL:
* _cdecl: referred to as the standard way
* __stdcall referred to as the Pascal way
Therefore if you want to call an external routine defined in a DLL supposed to be called using the `_cdecl` method, you have to use the '''dll32''' sub-language option. For `__stdcall` you need to use the '''dllwin32''' sub-language option. Here is an example:
<code>
my_cdecl_routine (a: INTEGER): POINTER
-- Encapsulation of a dll function with the `_cdecl' call mechanism.
external
"C [dll32 %"my_dll.dll%"] (int): EIF_POINTER"
end
my_stdcall_routine (a: INTEGER): POINTER
-- Encapsulation of a dll function with the `_stdcall' call mechanism.
external
"C [dllwin32 %"my_dll.dll%"] (int): EIF_POINTER"
end</code>
{{warning|Using '''dll32''' in cases calling for '''dllwin32''' and vice versa will cause your system to crash, because the C call stack will be corrupted. For more information please read your C compiler documentation. }}
===Windows API===
As described in the previous section concerning routines exported in a DLL, the Windows API is using the `__stdcall` convention. As a consequence, you cannot use the standard external mechanism to wrap them because it is using the `_cdecl` convention. However, you can easily wrap those function by using the '''macro''' sub-language.
Here is an example that has been taken from WEL, the Windows Eiffel Library, to encapsulate the Windows `SendMessage` function:
Windows defined SendMessage as:
<code lang="cpp">LRESULT SendMessage(
HWND hWnd, // handle to destination window
UINT Msg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);</code>
In WEL, the encapsulation is written as:
<code>
cwin_send_message (hwnd: POINTER; msg, wparam, param: INTEGER)
-- SDK SendMessage (without the result)
external
"C [macro %"wel.h%"] (HWND, UINT, WPARAM, LPARAM)"
alias
"SendMessage"
end</code>
{{seealso|<br/>
[[C++ Externals|C++ externals]] }}

View File

@@ -0,0 +1,11 @@
[[Property:title|Obsolete "external" interfaces]]
[[Property:weight|0]]
[[Property:uuid|1b72d727-711e-2cab-8010-d62842e5230a]]
{{UnderConstruction}}
The interface mechanisms for C and C++ on the following pages are now been superseded in favor of the mechanism described in the Eiffel standard.

View File

@@ -0,0 +1,5 @@
[[Property:title|Eiffel2Java class reference]]
[[Property:weight|0]]
[[Property:uuid|2cc96a02-8e55-3663-d0d5-0f2ec3ed4403]]
==View the [[ref:libraries/eiffel2java/reference/index|Eiffel2Java class reference]]==

View File

@@ -0,0 +1,104 @@
[[Property:title|Eiffel2Java Sample]]
[[Property:weight|1]]
[[Property:uuid|90ef17d4-8e23-34dd-1cb8-488533561dd4]]
This example shows how to create an instance of the Java Virtual Machine and the creation of an object of type <eiffel>test</eiffel>, a java class reproduced below:
<code lang="java">
(Java Code)
class test
{
test ()
{
my_integer = 10;
}
public int my_integer;
public static int my_static_integer;
public void my_method (int arg_int, String arg_string)
{
my_static_integer = arg_int;
my_integer = arg_int;
}
}
</code>
In order to run properly you need to read [[Eiffel2Java|the library requirement]] .
===Compiling the example===
Since the example is using the `test.java` class, the first step is to compile the java class using the `javac` command line utility from the JDK. Once it is done, copy the `test.class` either into $ISE_EIFFEL\examples\Eiffel2Java\EIFGENs\classic\W_code or else into $ISE_EIFFEL\examples\Eiffel2Java\EIFGENs\classic\F_code, depending on your compilation mode (freezing vs. finalizing).
===Running the example===
Once the example is compiled, you can run it and here is the expected output:
<code>
$ sample
Creating instance of class `test'
Value of `my_integer' is 10
Value of `my_static_integer' is 0
Calling `my_method' with (2, "String test")
Value of `my_integer' after call to `my_method' is 2
</code>
===Code description===
<code>(Eiffel Code)
class
EIFFEL_TO_JAVA
inherit
SHARED_JNI_ENVIRONMENT
create
make
feature -- Creation
make
local
class_test: JAVA_CLASS
instance_of_class_test: JAVA_OBJECT
fid: POINTER
value: INTEGER
j_args: JAVA_ARGS
do
--| Creation of the Java object
class_test := jni.find_class ("test")
create instance_of_class_test.create_instance (class_test, "()V", Void)
--| Access to a public attribute
fid := instance_of_class_test.field_id ("my_integer", "I")
-- 'fid' contains the id of the field 'my_integer'
-- 'value' contains the value of the field referenced
-- by 'fid'
value := instance_of_class_test.integer_attribute (fid)
--| Access to a static attribute using directly the JAVA_CLASS
fid := class_test.field_id ("my_static_integer", "I")
value := class_test.integer_attribute (fid)
--| Access to a static attribute using the attribute 'jclass'
fid := instance_of_class_test.jclass.field_id ("my_static_integer", "I")
value := instance_of_class_test.jclass.integer_attribute (fid)
--| Access to the method 'my_method'
-- Get the id of 'my_method'
fid := instance_of_class_test.method_id ("my_method", "(ILjava/lang/String;)V")
-- Create the set of arguments for 'my_method'
create j_args.make(2)
j_args.push_int (2)
j_args.push_string("String test")
-- Create the set of arguments for 'my_method'
-- Call to the void method referenced by 'fid'
instance_of_class_test.void_method (fid, j_args)
end -- make
end -- class EIFFEL_TO_JAVA</code>

View File

@@ -0,0 +1,159 @@
[[Property:title|Eiffel2Java Tutorial]]
[[Property:weight|0]]
[[Property:uuid|2d0fc62b-90e9-650b-2896-d92db66899c9]]
==Introduction==
The Java interface allows you to call Java routines or attributes from your Eiffel code. It uses the Java Native Interface (JNI) provided by the Java Development Kit (JDK). You can get more information about the JNI at:
[http://java.sun.com/j2se/1.5.0/docs/guide/jni/ http://java.sun.com/j2se/1.5.0/docs/guide/jni/]
===Requirements===
* JDK 1.1.8 or newer should be correctly set up (download it at [http://java.sun.com/javase/downloads/index.jsp http://java.sun.com/javase/downloads/index.jsp] )
* The environment variable CLASSPATH should defined (check with the JDK documentation on how to do so) and that it contains the Java classes you want to access.
* The environment variables should be setup correctly. See $ISE_EIFFEL\library\Eiffel2Java\README.txt for information how to do this.
===Limitations===
* In this version, you can only use one JNI environment.
* Only one thread can interact with the Java Virtual Machine (JVM).
* It is not possible to call Eiffel features from Java program.
* The Eiffel feature `destroy_vm` of `JAVA_VM` calls a C function of the Java NativeInterface that is not fully implemented in jdk 1.1.8. This function, called DestroyJavaVM, always returns -1 in jdk 1.1.8. For further information, go on the JNI pages at the address above.
==Interface classes==
===JNI_ENVIRONMENT===
Holds information about JNI environment. Potentially many JNI environments can exists at once, but more than one was never tested. This class provide the facilities to interact with the JVM:
* creation of instances of Java Classes
* exceptions mechanism
* destruction of the JVM
===SHARED_JNI_ENVIRONMENT===
Shared JNI environment. Since one JNI is needed per thread we limit Eiffel to having one thread that deals with Java. The class that calls Java routines or attributes must inherit from this class.
===JAVA_VM===
This class is used to initially load the JVM into the running program. This is the Eiffel representation of the JVM.
===JAVA_CLASS===
Access to Java classes. Static methods and attributes are accessed via this class.This is the Eiffel representation of a Java Class.
===JAVA_OBJECT===
This class gives Eiffel access to Java objects. You can use it directly or inherit from to and create a more convenient Eiffel class that makes the Java object look like an Eiffel object. The Eiffel representation of a Java Object.
{{warning|to access the static fields or routines of a Java Class, you have to use the features of a JAVA_CLASS instance!! }}
===JAVA_EXTERNALS===
JNI external declarations. Don't use this class directly.
===JAVA_***_ARRAY===
Access to Java array of "***". "***" can be all the usual types of Java (byte, short, int, float, double, char, boolean) or object if it is an array of Java Object (a String is considered as an object)
===JAVA_ARGS===
Class representing the arguments that can be passed to a Java method. See below about the signature of the methods
===JAVA_OBJECT_TABLE===
This class provides a mapping between Java and Eiffel objects
'''Mapping the Eiffel classes and the Java types:'''
The following table describes the mapping of Java primitive types and classes to Eiffel classes.
{|
|-
| '''Java type/class'''
| '''Eiffel class'''
|-
| boolean
| BOOLEAN
|-
| char, byte
| CHARACTER
|-
| short, int
| INTEGER
|-
| long
| INTEGER_64
|-
| float
| REAL
|-
| double
| DOUBLE
|-
| String
| STRING
|-
| void
| Void
|}
The interface does the mapping automatically. For example, if you call a Java method that returns a 'float', by using float_method you will get a REAL.
'''The signature of Java methods and attributes:'''
When you want to call a Java method or access a field, you need to specify its signature.The Eiffel to Java interface follows the JNI specifications. The table below summarizes the encoding for the Java type signatures:
{|
|-
| '''Signature'''
| '''Java Type'''
|-
| Z
| boolean
|-
| B
| byte
|-
| C
| char
|-
| S
| short
|-
| I
| int
|-
| J
| long
|-
| F
| float
|-
| D
| double
|-
| V
| void
|-
| [type
| type []
|}
The signature for a Java class has the following form:
<code lang=text>
L fully-qualified-class;</code>
For example, class String:
<code lang=text>
Ljava/lang/String;</code>
The signature for a method has the following form:
<code lang=text>
(arguments-types) returned-types</code>
For example, the signature of a method that takes as arguments an integer and a string and return void is:
<code lang=text>
(ILjava/lang/String;)V</code>

View File

@@ -0,0 +1,8 @@
[[Property:title|Eiffel2Java]]
[[Property:weight|4]]
[[Property:uuid|009ed581-1141-7db0-74bb-a9cbca15b904]]
==The Eiffel2Java Library==
Type: Library <br/>
Platform: Any

View File

@@ -0,0 +1,14 @@
[[Property:link_title|With other languages]]
[[Property:title|Including other languages]]
[[Property:weight|-12]]
[[Property:uuid|6029d6d9-bb73-5c74-02f6-70d202a65ceb]]
== Interacting with software in other languages ==
===C, C++, and Java===
With EiffelStudio you can encapsulate routines written in C , C++ and Java. This makes it possible to use powerful libraries written in other languages while still benefiting from the use of Eiffel for the overall design of your system.
It is also possible to make Eiffel routines available to be called by these languages. So, you can augment existing systems written in other languages with extensions built with Eiffel.
===Microsoft COM and .NET===
In addition to C, C++, and Java, you may find it valuable to use Eiffel with other technologies like Microsoft COM and the multiple languages of Microsoft .NET. You will find information about interacting with these technologies in our documentation specific to [[Microsoft Windows|support for Microsoft Windows]].