Next: , Up: Data passing conventions   [Contents]


14.3.1 C data passing conventions

For each of the Mercury types int, float, char, and string, there is a C typedef for the corresponding type in C: MR_Integer, MR_Float, MR_Char, and MR_String respectively.

In the current implementation, MR_Integer is a typedef for a signed integral type whose size is the same size as a pointer of type ‘void *’; MR_Float is a typedef for double (unless the program and the Mercury library was compiled with ‘--single-prec-float’, in which case it is a typedef for float); MR_Char is a typedef for a signed 32-bit integral type and MR_String is a typedef for ‘char *’.

Mercury variables of type int, float, char, or string are passed to and from C as C variables whose type is given by the corresponding typedef.

For the Mercury standard library type ‘bool.bool’, there is a corresponding C type, MR_Bool. C code can refer to the boolean data constructors ‘yes’ and ‘no’, as MR_YES and MR_NO respectively.

For the Mercury standard library type ‘builtin.comparison_result’, there is a corresponding C type, MR_Comparison_Result. C code can refer to the data constructors of this type, ‘(<)’, ‘(=)’ and ‘(>)’, as MR_COMPARE_LESS, MR_COMPARE_EQUAL and MR_COMPARE_GREATER respectively.

Mercury variables of a type for which there is a C ‘pragma foreign_type’ declaration (see Using foreign types from Mercury) will be passed as the corresponding C type.

Mercury tuple types are passed as MR_Tuple, which in the current implementation is a typedef for a pointer of type ‘void *’ if ‘--high-level-code’ is enabled, and a typedef for MR_Word otherwise.

Mercury variables of any other type are passed as a MR_Word, which in the current implementation is a typedef for an unsigned type whose size is the same size as a pointer. (Note: it would in fact be better for each Mercury type to map to a distinct abstract type in C, since that would be more type-safe, and thus we may change this in a future release. We advise programmers who are manipulating Mercury types in C code to use typedefs for each user-defined Mercury type, and to treat each such type as an abstract data type. This is good style and it will also minimize any compatibility problems if and when we do change this.)

Mercury lists can be manipulated by C code using the following macros, which are defined by the Mercury implementation.

MR_list_is_empty(list)     /* test if a list is empty */
MR_list_head(list)         /* get the head of a list */
MR_list_tail(list)         /* get the tail of a list */
MR_list_empty()            /* create an empty list */
MR_list_cons(head,tail)    /* construct a list with the given head and tail */

Note that the use of these macros is subject to some caveats (see Memory management for C).

The implementation provides the macro MR_word_to_float for converting a value of type MR_Word to one of type MR_Float, and the macro MR_float_to_word for converting a value of type MR_Float to one of type MR_Word. These macros must be used to perform these conversions since for some Mercury implementations ‘sizeof(MR_Float)’ is greater than ‘sizeof(MR_Word)’.

The following fragment of C code illustrates the correct way to extract the head of a Mercury list of floats.

MR_Float f;
f = MR_word_to_float(MR_list_head(list));

Omitting the call to MR_word_to_float in the above example would yield incorrect results for implementations where ‘sizeof(MR_Float)’ is greater than ‘sizeof(MR_Word)’.


Next: , Up: Data passing conventions   [Contents]