A C ‘pragma foreign_type’ declaration has the form:
:- pragma foreign_type("C", MercuryTypeName, "CForeignType").
:- pragma foreign_type("C", long_double, "long double").
The CForeignType can be any C type name that obeys the following restrictions. Function types, array types, and incomplete types are not allowed. The type name must be such that when declaring a variable in C of that type, that no part of the type name is required after the variable name. (This rule prohibits, for example, function pointer types such as ‘void (*)(void)’. However, it would be OK to use a typedef name which was defined as a function pointer type.)
C preprocessor directives (such as ‘#if’) may not be used in CForeignType. (You can however use a typedef name that refers to a type defined in a ‘pragma foreign_decl’ declaration, and the ‘pragma foreign_decl’ declaration may contain C preprocessor directives.)
With ‘--gc accurate’, foreign_types which are C pointer types must not point to the Mercury heap.
If the MercuryTypeName is the type of a parameter of a procedure defined using ‘pragma foreign_proc’, it will be passed to the foreign_proc’s foreign language code as CForeignType.
Furthermore, any Mercury procedure exported with ‘pragma foreign_export’ will use CForeignType as the type for any parameters whose Mercury type is MercuryTypeName.
The builtin Mercury type
c_pointer may be used to pass C pointers
between C functions which are called from Mercury. For example:
:- module pointer_example. :- interface. :- type complicated_c_structure. % Initialise the abstract C structure that we pass around in Mercury. :- pred initialise_complicated_structure(complicated_c_structure::uo) is det. % Perform a calculation on the C structure. :- pred do_calculation(int::in, complicated_c_structure::di, complicated_c_structure::uo) is det. :- implementation. % Our C structure is implemented as a c_pointer. :- type complicated_c_structure ---> complicated_c_structure(c_pointer). :- pragma foreign_decl("C", extern struct foo *init_struct(void); extern struct foo *perform_calculation(int, struct foo *); "); :- pragma foreign_proc("C", initialise_complicated_structure(Structure::uo), [will_not_call_mercury, may_call_mercury], " Structure = init_struct(); "). :- pragma foreign_proc("C", do_calculation(Value::in, Structure0::di, Structure::uo), [will_not_call_mercury, may_call_mercury], " Structure = perform_calculation(Value, Structure0); ").
We strongly recommend the use of ‘pragma foreign_type’ instead of
c_pointer as the use of ‘pragma foreign_type’ results in
more type-safe code.