Next: Using pragma foreign_enum for C, Up: Interfacing with C [Contents]
A C ‘pragma foreign_type’ declaration has the form:
:- pragma foreign_type("C", MercuryTypeName, "CForeignType").
For example,
:- 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, 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.)
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.
Next: Using pragma foreign_enum for C, Up: Interfacing with C [Contents]