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]