Next: , Previous: Formal semantics, Up: Top   [Contents]


16 Foreign language interface

This chapter documents the foreign language interface.


16.1 Calling foreign code from Mercury

Mercury procedures can be implemented using fragments of foreign language code using ‘pragma foreign_proc’.


16.1.1 pragma foreign_proc

A declaration of the form

:- pragma foreign_proc("Lang",
    Pred(Var1::Mode1, Var2::Mode2, …),
    Attributes, Foreign_Code).

or

:- pragma foreign_proc("Lang",
    Func(Var1::Mode1, Var2::Mode2, …) = (Var::Mode),
    Attributes, Foreign_Code).

means that any calls to the specified mode of Pred or Func will result in execution of the foreign code given in Foreign_Code written in language Lang, if Lang is selected as the foreign language code by this implementation. See the “Foreign Language Interface” chapter of the Mercury User’s Guide, for more information about how the implementation selects the appropriate ‘foreign_proc’ to use.

The foreign code fragment may refer to the specified variables (Var1, Var2, …, and Var) directly by name. It is an error for a variable to occur more than once in the argument list. These variables will have foreign language types corresponding to their Mercury types, as determined by language and implementation specific rules.

All ‘foreign_proc’ implementations are assumed to be impure. If they are actually pure or semipure, they must be explicitly promised as such by the user (either by using foreign language attributes specified below, or a ‘promise_pure’ or ‘promise_semipure’ pragma as specified in Impurity).

Additional restrictions on the foreign language interface code depend on the foreign language and compilation options. For more information, including the list of supported foreign languages and the strings used to identify them, see the language specific information in the “Foreign Language Interface” chapter of the Mercury User’s Guide.

If there is a pragma foreign_proc declaration for any mode of a predicate or function, then there must be either a clause or a pragma foreign_proc declaration for every mode of that predicate or function.

Here is an example of code using ‘pragma foreign_proc’. The following code defines a Mercury function ‘sin/1’ which calls the C function ‘sin()’ of the same name.

:- func sin(float) = float.
:- pragma foreign_proc("C",
    sin(X::in) = (Sin::out),
    [promise_pure, may_call_mercury],
"
    Sin = sin(X);
").

If the foreign language code does not recursively invoke Mercury code, as in the above example, then you can use ‘will_not_call_mercury’ in place of ‘may_call_mercury’ in the declarations above. This allows the compiler to use a slightly more efficient calling convention. (If you use this form, and the foreign code does invoke Mercury code, then the behaviour is undefined — your program may misbehave or crash.)

If there are both Mercury definitions and foreign_proc definitions for a procedure and/or foreign_proc definitions for different languages, it is implementation-defined which definition is used.

For pure and semipure procedures, the declarative semantics of the foreign_proc definitions must be the same as that of the Mercury code. The only thing that is allowed to differ is the efficiency (including the possibility of non-termination) and the order of solutions.

It is an error for a procedure with a ‘pragma foreign_proc’ declaration to have a determinism of multi or nondet.

Since foreign_procs with the determinism multi or nondet cannot be defined directly, procedures with those determinisms that require foreign code in their implementation must be defined using a combination of Mercury clauses and (semi)deterministic foreign_procs. The following implementation for the standard library predicate ‘string.append/3’ in the mode ‘append(out, out, in) is multi’ illustrates this technique:

:- pred append(string, string, string).
:- mode append(out, out, in) is multi.

append(S1, S2, S3) :-
    S3Len = string.length(S3),
    append_2(0, S3Len, S1, S2, S3).

:- pred append_2(int::in, int::in, string::out, string::out, string::in) is multi.

append_2(NextS1Len, S3Len, S1, S2, S3) :-
    ( if NextS1Len = S3Len then
        append_3(NextS1Len, S3Len, S1, S2, S3)
    else
        (
            append_3(NextS1Len, S3Len, S1, S2, S3)
        ;
            append_2(NextS1Len + 1, S3Len, S1, S2, S3)
        )
    ).

:- pred append_3(int::in, int::in, string::out, string::out, string::in) is det.

:- pragma foreign_proc("C",
    append_3(S1Len::in, S3Len::in, S1::out, S2::out, S3::in),
    [will_not_call_mercury, promise_pure],
"
    S1 = allocate_string(S1Len);   /* Allocate a new string of length S1Len */
    memcpy(S1, S3, S1Len);
    S1[S1Len] = '\\0';
    S2 = allocate_string(S2, S3Len - S1Len);
    strcpy(S2, S3Len + S1Len);
").


16.1.2 Foreign code attributes

As described above, ‘pragma foreign_proc’ declarations may include a list of attributes describing properties of the given foreign function or code. All Mercury implementations must support the attributes listed below. They may also support additional attributes.

The attributes which must be supported by all implementations are as follows:

may_call_mercury’/‘will_not_call_mercury

This attribute declares whether or not execution inside this foreign language code may call back into Mercury or not. The default, in case neither is specified, is ‘may_call_mercury’. Specifying ‘will_not_call_mercury’ may allow the compiler to generate more efficient code. If you specify ‘will_not_call_mercury’, but the foreign language code does invoke Mercury code, then the behaviour is undefined.

promise_pure’/‘promise_semipure

This attribute promises that the purity of the given predicate or function definition is pure or semipure. It is equivalent to a corresponding ‘pragma promise_pure’ or ‘pragma promise_semipure’ declaration (see Impurity). If omitted, the clause specified by the ‘foreign_proc’ is assumed to be impure.

thread_safe’/‘not_thread_safe’/‘maybe_thread_safe

This attribute declares whether or not it is safe for multiple threads to execute this foreign language code concurrently. The default, in case none is specified, is ‘not_thread_safe’. If the foreign language code is declared ‘thread_safe’, then the Mercury implementation is permitted to execute the code concurrently from multiple threads without taking any special precautions. If the foreign language code is declared ‘not_thread_safe’, then the Mercury implementation must not invoke the code concurrently from multiple threads. If the Mercury implementation does use multithreading, then it must take appropriate steps to prevent this. (The multithreaded version of the Melbourne Mercury implementation protects ‘not_thread_safe’ code using a mutex: C code that is not thread-safe has code inserted around it to obtain and release a mutex. All non-thread-safe foreign language code shares a single mutex.) If the foreign language code is declared ‘maybe_thread_safe’ then whether the code is considered ‘thread_safe’ or ‘not_thread_safe’ depends upon a compiler flag. This attribute is useful when the thread safety of the foreign code itself is conditional. The Melbourne Mercury compiler uses the ‘--maybe-thread-safe’ option to set the value of the ‘maybe_thread_safe’ attribute.

Additional attributes which are supported by the Melbourne Mercury compiler are as follows:

tabled_for_io

This attribute should be attached to foreign procedures that do I/O. It tells the debugger to make calls to the foreign procedure idempotent. This allows the debugger to safely retry across such calls and also allows safe declarative debugging of code containing such calls. For more information, see the “I/O tabling” section of the Mercury User’s Guide. If the foreign procedure contains gotos or static variables then the ‘pragma no_inline’ directive should also be given. Note that currently I/O tabling will only be done for foreign procedures that take a pair of I/O state arguments. Impure foreign procedures that perform I/O will not be made idempotent, even if the tabled_for_io attribute is present. Note also that the tabled_for_io attribute will likely be replaced in a future release with a more general solution.

terminates’/‘does_not_terminate

This attribute specifies the termination properties of the given predicate or function definition. It is equivalent to the corresponding ‘pragma terminates’ or ‘pragma does_not_terminate’ declaration. If omitted, the termination property of the procedure is determined by the value of the ‘may_call_mercury’/‘will_not_call_mercury’ attribute. See Termination analysis for more details.

will_not_throw_exception

This attribute promises that the given predicate or function will not make calls back to Mercury that may result in an exception being thrown. It is an error to apply this attribute to procedures that have determinism erroneous. This attribute is ignored for code that is declared as not making calls back to Mercury via the ‘will_not_call_mercury’ attribute. Note: predicates or functions that have polymorphic arguments but do not explicitly throw an exception, via a call to ‘exception.throw/1’ or ‘require.error/1’, may still throw exceptions because they may be called with arguments whose types have user-defined equality or comparison predicates. If these user-defined equality or comparison predicates throw exceptions then unifications or comparisons involving these types may also throw exceptions. As such, we recommend that only implementors of the Mercury system use this annotation for polymorphic predicates and functions.

will_not_modify_trail/may_modify_trail

This attribute declares whether or not a foreign procedure modifies the trail (see Trailing). Specifying that a foreign procedure will not modify the trail may allow the compiler to generate more efficient code for that procedure. In compilation grades that do not support trailing, this attribute is ignored. The default, in case none is specified, is ‘may_modify_trail’.

will_not_call_mm_tabled/may_call_mm_tabled

This attribute declares whether or not a foreign procedure makes calls back to Mercury procedures that are evaluated using minimal model tabling (see Tabled evaluation). Specifying that a foreign procedure will not call procedures evaluated using minimal model tabling may allow the compiler to generate more efficient code. In compilation grades that do not support minimal model tabling, this attribute is ignored. These attributes may not be used with procedures that do not make calls back to Mercury, i.e. that have the ‘will_not_call_mercury’ attribute. The default for foreign procedures that ‘may_call_mercury’, in case none is specified, is ‘may_call_mm_tabled’.

affects_liveness/does_not_affect_liveness

This attribute declares whether or not a foreign procedure uses and/or modifies any part of the Mercury virtual machine (registers, stack slots) through means other than its arguments. The ‘affects_liveness’ attribute says that it does; The ‘does_not_affect_liveness’ attribute says that it does not. In the absence of either attribute, the compiler assumes ‘affects_liveness’, unless the code of the foreign_proc in question is empty.

may_duplicate/may_not_duplicate

This attribute tells the compiler whether it is allowed to duplicate the foreign code fragment through optimizations such as inlining. The ‘may_duplicate’ attribute says that it may; the ‘may_not_duplicate’ attribute says that it may not. In the absence of either attribute, the compiler is allowed make its own judgement in the matter, based on factors such as the size of the code fragment.

may_export_body/may_not_export_body

This attribute tells the compiler whether it is allowed to duplicate the foreign code fragment outside of the target file for the module that defines the foreign procedure. The ‘may_export_body’ attribute says that it may; the ‘may_not_export_body’ attribute says that it may not. The default is ‘may_export_body’.


16.2 Calling Mercury from foreign code

Mercury procedures may be exported so that they can be called by code written in a foreign language.

A declaration of the form:

:- pragma foreign_export("Lang",
    Pred(Mode1, Mode2, …), "ForeignName").

or

:- pragma foreign_export("Lang",
    Func(Mode1, Mode2, …) = Mode,
    "ForeignName").

exports a procedure for use by foreign language Lang. For each exported procedure, the Mercury implementation will create an interface to the named Mercury procedure in the foreign language using the name ForeignName. The form of this interface is dependent upon the specified foreign language. For further details see the language specific information below.

It is an error to export a Mercury procedure that has a determinism of multi or nondet.


16.3 Data passing conventions

For each supported foreign language, we explain how to map a Mercury type to a type in that foreign language. We also map the Mercury parameter passing convention to the foreign language’s parameter passing convention.


16.3.1 C data passing conventions

The Mercury primitive types are mapped to the following C types:

Mercury typeC type
intMR_Integer
int8int8_t
int16int16_t
int32int32_t
int64int64_t
uintMR_Unsigned
uint8uint8_t
uint16uint16_t
uint32uint32_t
uint64uint64_t
floatMR_Float
charMR_Char
stringMR_String

In the current implementation, MR_Integer is a typedef for a signed integral type which is the same size as a pointer of type ‘void *’; MR_Unsigned is a typedef for an unsigned integral type which 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 primitive types are passed to and from C as C variables of the corresponding C type.

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)’.

Similarly, the implementation provides the macros MR_word_to_int64 and MR_word_to_uint64 for converting values of type MR_Word to ones of type int64_t or uint64_t respectively, and the macros MR_int64_to_word and MR_uint64_to_word for converting values of type int64_t or uint64_t respectively to ones of type MR_Word. These macros must be used to perform these conversions since for some Mercury implementations ‘sizeof(int64_t)’ or ‘sizeof(uint64_t)’ are greater than ‘sizeof(MR_Word)’.


16.3.2 C# data passing conventions

The Mercury primitive types are mapped to the following Common Language Infrastructure (CLI) and C# types:

Mercury typeCLI typeC# type
intSystem.Int32int
int8System.Int8sbyte
int16System.Int16short
int32System.Int32int
int64System.Int64long
uintSystem.UInt32uint
uint8System.UInt8byte
uint16System.UInt16ushort
uint32System.UInt32uint
uint64System.UInt64ulong
floatSystem.Doubledouble
charSystem.Int32int
stringSystem.Stringstring

Note that the Mercury type char is mapped like int; not to the CLI type System.Char because that only holds 16-bit numeric values.

For the Mercury standard library type ‘bool.bool’, there is a corresponding C# type, mr_bool.Bool_0. C# code can refer to the boolean data constructors ‘yes’ and ‘no’, as mr_bool.YES and mr_bool.NO respectively.

For the Mercury standard library type ‘builtin.comparison_result’, there is a corresponding C# type, builtin.Comparison_result_0. C# code can refer to the data constructors of this type, ‘(<)’, ‘(=)’ and ‘(>)’, as builtin.COMPARE_LESS, builtin.COMPARE_EQUAL and builtin.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. Both reference and value types are supported.

Mercury tuple types are passed as ‘object[]’ where the length of the array is the number of elements in the tuple.

Mercury variables whose type is a type variable will be passed as System.Object.

Mercury variables whose type is a Mercury discriminated union type will be passed as a CLI type whose type name is determined from the Mercury type name (ignoring any type parameters) followed by an underscore and then the type arity, expressed as a decimal integer. The first character of the type name will have its case inverted, and the name may be mangled to satisfy C# lexical rules.

For example, the following Mercury type corresponds to the C# class that follows (some implementation details elided):

:- type maybe(T)
    --->    yes(yes_field :: T)
    ;       no.

public static class Maybe_1 {
    public static class Yes_1 : Maybe_1 {
        public object yes_field;
        public Yes_1(object x) { … }
    }
    public static class No_0 : Maybe_1 {
        public No_0() { … }
    }
}

C# code generated by the Mercury compiler is placed in the ‘mercury’ namespace. Mercury module qualifiers are converted into a C# class name by concatenating the components with double underscore separators (‘__’). For example the Mercury type ‘foo.bar.baz/1’ will be passed as the C# type ‘mercury.foo__bar.Baz_1’.

Mercury array types are mapped to System.Array.

Mercury variables whose type is a Mercury equivalence type will be passed as the representation of the right hand side of the equivalence type.

This mapping is subject to change and you should try to avoid writing code that relies heavily upon a particular representation of Mercury terms.

Mercury arguments declared with input modes are passed by value to the C# function.

Arguments of type ‘io.state’ or ‘store.store(_)’ are not passed or returned at all. (The reason for this is that these types represent mutable state, and in C# modifications to mutable state are done via side effects, rather than argument passing.)

The handling of multiple output arguments is as follows.

If the Mercury procedure is deterministic and has no output arguments, then the return type of the C# function is ‘void’; if it has one output argument, then the return value of the function is that output argument.

If the Mercury procedure is deterministic and has two or more output arguments, then the return type of the C# function is ‘void’. At the position of each output argument, the C# function has an ‘out’ parameter.

If the Mercury procedure is semi-deterministic then the C# function returns a ‘bool’. A ‘true’ return value denotes success and ‘false’ denotes failure. Output arguments are handled in the same way as multiple outputs for deterministic procedures, using ‘out’ parameters. On failure the values of the ‘val’ fields are undefined.

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

bool      list.is_empty(List_1 list)     // test if a list is empty
object    list.det_head(List_1 list)     // get the head of a list
List_1    list.det_tail(List_1 list)     // get the tail of a list
List_1    list.empty_list()              // create an empty list
List_1    list.cons(object head, List_1 tail)
                                         // construct a list with
                                         //  the given head and tail

16.3.3 Java data passing conventions

The Mercury primitive types are mapped to the following Java types:

Mercury typeJava type
intint
int8byte
int16short
int32int
int64long
uintint
uint8byte
uint16short
uint32int
uint64long
floatdouble
charint
stringjava.lang.String

Note that since Java lacks unsigned integer types, Mercury’s unsigned integer types correspond to signed integer types in Java.

Also, note that the Mercury type char is mapped like int; not to the Java type char because that only holds 16-bit numeric values.

For the Mercury standard library type ‘bool.bool’, there is a corresponding Java type, bool.Bool_0. Java code can refer to the boolean data constructors ‘yes’ and ‘no’, as bool.YES and bool.NO respectively.

For the Mercury standard library type ‘builtin.comparison_result’, there is a corresponding Java type, builtin.Comparison_result_0. Java code can refer to the data constructors of this type, ‘(<)’, ‘(=)’ and ‘(>)’, as builtin.COMPARE_LESS, builtin.COMPARE_EQUAL and builtin.COMPARE_GREATER respectively.

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

Mercury tuple types are passed as java.lang.Object[] where the length of the array is the number of elements in the tuple.

Mercury variables whose types are universally quantified type variables will have generic types. Mercury variables whose types are existentially quantified type variables will be passed as java.lang.Object.

Mercury variables whose type is a Mercury discriminated union type will be passed as a Java type whose type name is determined from the Mercury type name (ignoring any type parameters) followed by an underscore and then the type arity, expressed as a decimal integer. The first character of the type name will have its case inverted, and the name may be mangled to satisfy Java lexical rules. Generics are used in the Java type for any type parameters.

For example, the following Mercury type corresponds to the Java class that follows (some implementation details elided):

:- type maybe(T)
    --->    yes(yes_field :: T)
    ;       no.

public static class Maybe_1<T> {
    public static class Yes_1<T> extends Maybe_1 {
        public T yes_field;
        public Yes_1(T x) { … }
    }
    public static class No_0<T> extends Maybe_1 {
        public No_0() { … }
    }
}

Java code generated by the Mercury compiler is placed in the ‘jmercury’ package. Mercury module qualifiers are converted into a Java class name by concatenating the components with double underscore separators (‘__’). For example the Mercury type ‘foo.bar.baz/1’ will be passed as the Java type ‘jmercury.foo__bar.Baz_1’.

Mercury array types are mapped to Java array types.

Mercury variables whose type is a Mercury equivalence type will be passed as the representation of the right hand side of the equivalence type.

This mapping is subject to change and you should try to avoid writing code that relies heavily upon a particular representation of Mercury terms.

Mercury arguments declared with input modes are passed by value to the corresponding Java function. If the Mercury procedure is a function whose result has an input mode, then the Mercury function result is appended to the list of input parameters, so that the Mercury function result becomes the last parameter to the corresponding Java function.

Arguments of type ‘io.state’ or ‘store.store(_)’ are not passed or returned at all. (The reason for this is that these types represent mutable state, and in Java modifications to mutable state are done via side effects, rather than argument passing.)

The handling of multiple output arguments is as follows.

If the Mercury procedure is deterministic and has no output arguments, then the return type of the Java function is void; if it has one output argument, then the return value of the function is that output argument.

If the Mercury procedure is deterministic and has two or more output arguments, then the return type of the Java function is void. At the position of each output argument, the Java function takes a value of the type ‘jmercury.runtime.Ref<T>’ where ‘T’ is the Java type corresponding to the type of the output argument. ‘Ref’ is a class with a single field ‘val’, which is assigned the output value when the function returns.

If the Mercury procedure is semi-deterministic, then the Java function returns a ‘boolean’. A ‘true’ return value denotes success and ‘false’ denotes failure. Output arguments are handled in the same way as multiple outputs for deterministic procedures, using the ‘Ref’ class. On failure the values of the ‘val’ fields are undefined.

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

boolean   list.is_empty(List_1<E> list)     // test if a list is empty
E         list.det_head(List_1<E> list)     // get the head of a list
List_1<E> list.det_tail(List_1<E> list)     // get the tail of a list
List_1<E> list.empty_list()                 // create an empty list
<E, F extends E> List_1<E> list.cons(F head, List_1<E> tail)
                                            // construct a list with
                                            // the given head and tail

16.4 Using foreign types from Mercury

Types defined in a foreign language can be accessed in Mercury using a declaration of the form

:- pragma foreign_type(Lang, MercuryTypeName, ForeignTypeDescriptor).

This defines MercuryTypeName as a synonym for type ForeignTypeDescriptor defined in the foreign language Lang. MercuryTypeName must be the name of either an abstract type or a discriminated union type. In both cases, MercuryTypeName must be declared with ‘:- type’ as usual. The ‘pragma foreign_type’ must not have wider visibility than the type declaration (if the ‘pragma foreign_type’ declaration is in the interface, the ‘:- type’ declaration must be also).

If MercuryTypeName names a discriminated union type, that type cannot be the base type of any subtypes, nor can it be a subtype itself (see Subtypes).

ForeignTypeDescriptor defines how the Mercury type is mapped for a particular foreign language. Specific syntax is given in the language specific information below.

MercuryTypeName is treated as an abstract type at all times in Mercury code. However, if MercuryTypeName is one of the parameters of a foreign_proc for Lang, and the ‘pragma foreign_type’ declaration is visible to the foreign_proc, it will be passed to that foreign_proc as specified by ForeignTypeDescriptor.

The same type may have a foreign language definition for more than one foreign language. The definition used in the generated code will be the one for the foreign language that is most appropriate for the target language of the compilation (see the language specific information below for details). All the foreign language definitions must have the same visibility.

A type which has one or more foreign language definitions may also have a Mercury definition, which must define a discriminated union type. The constructors for this Mercury type will only be visible in Mercury clauses for predicates or functions with ‘pragma foreign_proc’ clauses for all of the languages for which there are ‘foreign_type’ declarations for the type.

You can also associate assertions about the properties of the foreign type with the ‘foreign_type’ declaration, using the following syntax:

:- pragma foreign_type(Lang, MercuryTypeName, ForeignTypeDescriptor,
    [ForeignTypeAssertion, …]).

Currently, three kinds of assertions are supported.

The ‘can_pass_as_mercury_type’ assertion states that on the C backends, values of the given type can be passed to and from Mercury code without boxing, via simple casts, which is faster. This requires the type to be either an integer type or a pointer type, and requires it to be castable to ‘MR_Word’ and back without loss of information (which means that its size may not be greater than the size of ‘MR_Word’).

The ‘word_aligned_pointer’ assertion implies ‘can_pass_as_mercury_type’ and additionally states that values of the given type are pointer values clear in the tag bits. It allows the Mercury implementation to avoid boxing values of the given type when the type appears as the sole argument of a data constructor.

The ‘stable’ assertion is meaningful only in the presence of the ‘can_pass_as_mercury_type’ or ‘word_aligned_pointer’ assertions. It states that either the C type is an integer type, or it is a pointer type pointing to memory that will never change. Together, these assertions are sufficient to allow tabling (see Tabled evaluation) and the ‘compare_representation’ primitive to work on values of such types.

Violations of any of these assertions are very likely to result in the generated executable silently doing the wrong thing, giving no clue to where the problem might be. Since deciding whether a C type satisfies the conditions of these assertions requires knowledge of the internals of the Mercury implementation, we do not recommend the use of any of these assertions unless you are confident of your expertise in those internals.

As with discriminated union types, programmers can specify the unification and/or comparison predicates to use for values of the type using the following syntax (see User-defined equality and comparison):

:- pragma foreign_type(Lang, MercuryTypeName, ForeignTypeDescriptor)
        where equality is EqualityPred, comparison is ComparePred.

You can use Mercury foreign language interfacing declarations which specify language X to interface to types that are actually written in a different language Y, provided that X and Y have compatible interface conventions. Support for this kind of compatibility is described in the language specific information below.


16.5 Using foreign enumerations in Mercury code

While a ‘pragma foreign_type’ declaration imports a foreign type into Mercury, a ‘pragma foreign_enum’ declaration imports the values of the constants of an enumeration type into Mercury.

While languages such as C have special syntax for defining enumeration types, in Mercury, an enumeration type is simply an ordinary discriminated union type whose function symbols all have arity zero.

Given an enumeration type such as

:- type unix_file_permissions
    --->    user_read
    ;       user_write
    ;       user_executable
    ;       group_read
    ;       group_write
    ;       group_executable
    ;       other_read
    ;       other_write
    ;       other_executable.

the values used to represent each constant are usually decided by the Mercury compiler. However, the values assigned this way may not match the values expected by foreign language code that uses values of the enumeration, and even if they happen to match, programmers probably would not want to rely on this coincidence.

This is why Mercury supports a mechanism that allows programmers to specify the representation of each constant in an enumeration type when generating code for a given target language. This mechanism is the ‘pragma foreign_enum’ declaration, which looks like this:

:- pragma foreign_enum("C", unix_file_permissions/0,
[
    user_read        - "S_IRUSR",
    user_write       - "S_IWUSR",
    user_executable  - "S_IXUSR",
    group_read       - "S_IRGRP",
    group_write      - "S_IWGRP",
    group_executable - "S_IXGRP",
    other_read       - "S_IROTH",
    other_write      - "S_IWOTH",
    other_executable - "S_IXOTH"
]).

(Unix systems have a standard header file that defines each of ‘S_IRUSR’, …, ‘S_IXOTH’ as macros that each expand to an integer constant; these constants happen not to be the ones that the Mercury compiler would assign to those constants.)

The general form of ‘pragma foreign_enum’ declarations is

:- pragma foreign_enum("Lang", MercuryType, CtorValues).

where CtorValues is a list of pairs of the form:

[
    ctor_0 - "ForeignValue_0",
    ctor_1 - "ForeignValue_1",
    …
    ctor_N - "ForeignValue_N"
]

The first element of each pair is a constant (function symbol of arity 0) of the type MercuryType, and the second is either a numeric or a symbolic name for the integer value in the language Lang that the programmer wants to be used to represent that constructor.

The mapping defined by this list of pairs must form a bijection, i.e. the list must map distinct constructors to distinct values, and vice versa. The Mercury compiler is not required to check this, because it cannot; even if two symbolic names (such as C macros) are distinct, they may expand to the same integer in the target language.

Mercury implementations may impose further foreign-language-specific restrictions on the form that values used to represent enumeration constructors may take. See the language specific information below for details.

It is an error for any given MercuryType to be the subject of more than one ‘pragma foreign_enum’ declaration for any given foreign language, since that would amount to an attempt to specify two or more (probably) conflicting representations for each of the type’s function symbols.

A ‘pragma foreign_enum’ declaration must occur in the implementation section of the module that defines the type MercuryType. Because of this, the names of the constants need not and must not be module qualified.

Note that the default comparison for types that are the subject of a ‘pragma foreign_enum’ declaration will be defined by the foreign values, rather than the order of the constructors in the type declaration (as would otherwise be the case).


16.6 Using Mercury enumerations in foreign code

A ‘pragma foreign_enum’ declaration imports the values of the constants of an enumeration type into Mercury. However, sometimes one needs the reverse: the ability to export the values of the constants of an enumeration type (whether those values were assigned by ‘foreign_enum’ pragmas or not) from Mercury to foreign language code in ‘foreign_proc’ and ‘foreign_code’ pragmas. This is what ‘pragma foreign_export_enum’ declarations are for.

These pragmas have the following general form:

:- pragma foreign_export_enum("Lang", MercuryType,
    Attributes, Overrides).

When given such a pragma, the compiler will define a symbolic name in language Lang for each of the constructors of MercuryType (which must be an enumeration type). Each symbolic name allows code in that foreign language to create a value corresponding to that of the constructor it represents. (The exact mechanism used depends upon the foreign language; see the language specific information below for further details.)

For each foreign language, there is a default mapping between the name of a Mercury constructor and its symbolic name in the language Lang. This default mapping is not required to map every valid constructor name to a valid name in language Lang; where it does not, the programmer must specify a valid symbolic name. The programmer may also choose to map a constructor to a symbolic name that differs from the one supplied by the default mapping for language Lang. Overrides is a list whose elements are pairs of constructor names and strings. The latter specify the name that the implementation should use as the symbolic name in the foreign language. Overrides has the following form:

[cons_I - "symbol_I", …, cons_J - "symbol_J"]

This can be used to provide either a valid symbolic name where the default mapping does not, or to override a valid symbolic name generated by the default mapping. This argument may be omitted if Overrides is empty.

The argument Attributes is a list of optional attributes. If empty, it may be omitted from the ‘pragma foreign_export_enum’ declaration if the Overrides argument is also omitted. The following attributes must be supported by all Mercury implementations.

prefix(Prefix)

Prefix each symbolic name, regardless of how it was generated, with the string Prefix. A ‘pragma foreign_export_enum’ declaration may contain at most one ‘prefix’ attribute.

uppercase

Convert any alphabetic characters in a Mercury constructor name to uppercase when generating the symbolic name using the default mapping. Symbolic names specified by the programmer using Overrides are not affected by this attribute. If the ‘prefix’ attribute is also specified, then the prefix is added to the symbolic name after the conversion to uppercase has been performed, i.e. the characters in the prefix are not affected by the ‘uppercase’ attribute.

The implementation does not check the validity of a symbolic name in the foreign language until after the effects of any attributes have been applied. This means that attributes may cause an otherwise valid symbolic name to become invalid, or vice versa.

A Mercury module may contain ‘pragma foreign_export_enum’ declarations that refer to imported types, subject to the usual visibility restrictions.

A Mercury module, or program, may contain more than one ‘pragma foreign_export_enum’ declaration for a given Mercury type for a given language. This can be useful when a project is transitioning from using one naming scheme for Mercury constants in foreign code to another naming scheme.

It is an error if the mapping between constructors and symbolic names in a ‘pragma foreign_export_enum’ declaration does not form a bijection. It is also an error if two separate ‘pragma foreign_export_enum’ declarations for a given foreign language, whether or not for the same type, specify the same symbolic name, since in that case, the Mercury compiler would generate two conflicting definitions for that symbolic name. However, the Mercury implementation is not required to check either condition.

A ‘pragma foreign_export_enum’ declaration may occur only in the implementation section of a module.


16.7 Adding foreign declarations

Foreign language declarations (such as type declarations, header file inclusions or macro definitions) can be included in the Mercury source file as part of a ‘foreign_decl’ declaration of the form

:- pragma foreign_decl("Lang", DeclCode).

This declaration will have effects equivalent to including the specified DeclCode in an automatically generated source file of the specified programming language, in a place appropriate for declarations, and linking that source file with the Mercury program (after having compiled it with a compiler for the specified programming language, if appropriate).

Entities declared in ‘pragma foreign_decl’ declarations are visible in ‘pragma foreign_code’, ‘pragma foreign_type’, ‘pragma foreign_proc’, and ‘pragma foreign_enum’ declarations that specify the same foreign language and occur in the same Mercury module.

By default, the contents of ‘pragma foreign_decl’ declarations are also visible in the same kinds of declarations in other modules that import the module containing the ‘pragma foreign_decl’ declaration. This is because they may be required to make sense of types defined using ‘pragma foreign_type’ and/or predicates defined using ‘pragma foreign_proc’ in the containing module, and these may be visible in other modules, especially in the presence of intermodule optimization,

If you do not want the contents of a ‘pragma foreign_decl’ declaration to be visible in foreign language code in other modules, you can use the following variant of the declaration:

:- pragma foreign_decl("Lang", local, DeclCode).

Note: currently only the C backend supports this variant of the ‘pragma foreign_decl’ declaration.

The Melbourne Mercury implementation additionally supports the forms

:- pragma foreign_decl("Lang", include_file("Path")).
:- pragma foreign_decl("Lang", local, include_file("Path")).

These have the same effects as the standard forms except that the contents of the file referenced by Path are included in place of the string literal in the last argument, without further interpretation. Path may be an absolute path to a file, or a path to a file relative to the directory that contains the source file of the module containing the declaration. The interpretation of the path is platform-dependent. If the filesystem uses a different character set or encoding from the Mercury source file (which must be UTF-8), the file may not be found.

mmc --make’ and ‘mmake’ treat included files as dependencies of the module.


16.8 Declaring Mercury exports to other modules

The declarations for Mercury predicates or functions exported to a foreign language using a ‘pragma foreign_export’ declaration are visible to foreign code in a ‘pragma foreign_code’ or ‘pragma foreign_proc’ declaration of the same module, and also in those of any submodules. By default, they are not visible to the foreign code in ‘pragma foreign_code’ or ‘pragma foreign_proc’ declarations in any other module, but this default can be overridden (giving access to all other modules) using a declaration of the form:

:- pragma foreign_import_module("Lang", ImportedModule).

where ImportedModule is the name of the module containing the ‘pragma foreign_export’ declarations.

If Lang is "C", this is equivalent to

:- pragma foreign_decl("C", "#include ""ImportedModule.mh""").

where ImportedModule.mh is the automatically generated header file containing the C declarations for the predicates and functions exported to C.

pragma foreign_import_module’ should be used instead of the explicit #include because ‘pragma foreign_import_module’ tells the implementation that ImportedModule.mh must be built before the object file for the module containing the ‘pragma foreign_import_module’ declaration.

Note that the Melbourne Mercury implementation often behaves as if ‘pragma foreign_import_module’ declarations were implicitly added to modules. However, programmers should not should not depend on this behaviour; they should always write explicit ‘pragma foreign_import_module’ declarations wherever they are needed.


16.9 Adding foreign definitions

Definitions of foreign language entities (such as functions or global variables) may be included using a declaration of the form

:- pragma foreign_code("Lang", Code).

This declaration will have effects equivalent to including the specified Code in an automatically generated source file of the specified programming language, in a place appropriate for definitions, and linking that source file with the Mercury program (after having compiled it with a compiler for the specified programming language, if appropriate).

Entities declared in ‘pragma foreign_code’ declarations are visible in ‘pragma foreign_proc’ declarations that specify the same foreign language and occur in the same Mercury module.

The Melbourne Mercury implementation additionally supports the form

:- pragma foreign_code("Lang", include_file("Path")).

This has the same effect as the standard form except that the contents of the file referenced by Path are included in place of the string literal in the last argument, without further interpretation. Path may be an absolute path to a file, or a path to a file relative to the directory that contains the source file of the module containing the declaration. The interpretation of the path is platform-dependent. If the filesystem uses a different character set or encoding from the Mercury source file (which must be UTF-8), the file may not be found.

mmc --make’ and ‘mmake’ treat included files as dependencies of the module.


16.10 Language specific bindings

All Mercury implementations should support interfacing with C. The set of other languages supported is implementation-defined. A suitable compiler or assembler for the foreign language must be available on the system.

The Melbourne Mercury implementation supports interfacing with the following languages:

C

Use the string "C" to set the foreign language to C.

C#

Use the string "C#" to set the foreign language to C#.

Java

Use the string "Java" to set the foreign language to Java.


16.10.1 Interfacing with C


16.10.1.1 Using pragma foreign_type for C

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.


16.10.1.2 Using pragma foreign_enum for C

Foreign enumeration values in C must be constants of type MR_Integer. A foreign enumeration value may be specified by one of the following:


16.10.1.3 Using pragma foreign_export_enum for C

For C the symbolic names generated by a ‘pragma foreign_export_enum’ must form valid C identifiers. These identifiers are used as the names of preprocessor macros. The body of each of these macros expands to a value that is identical to that of the constructor to which the symbolic name corresponds in the mapping established by the ‘pragma foreign_export_enum declaration.

As noted in the C data passing conventions, the type of these values is MR_Word.

The default mapping used by ‘pragma foreign_export_enum’ declarations for C is to use the Mercury constructor name as the base of the symbolic name. For example, the symbolic name for the Mercury constructor ‘foo’ would be foo.


16.10.1.4 Using pragma foreign_proc for C

The input and output variables will have C types corresponding to their Mercury types, as determined by the rules specified in C data passing conventions.

The C code fragment may declare local variables, up to a total size of 10kB for the procedure. If a procedure requires more than this for its local variables, the code can be moved into a separate function (defined in a ‘pragma foreign_code’ declaration, for example).

The C code fragment should not declare any labels or static variables unless there is also a ‘pragma no_inline’ declaration or a ‘may_not_duplicate’ foreign code attribute for the procedure. The reason for this is that otherwise the Mercury implementation may inline the procedure by duplicating the C code fragment for each call. If the C code fragment declared a static variable, inlining it in this way could result in the program having multiple instances of the static variable, rather than a single shared instance. If the C code fragment declared a label, inlining it in this way could result in an error due to the same label being defined twice inside a single C function.

C code in a pragma foreign_proc declaration for any procedure whose determinism indicates that it can fail must assign a truth value to the macro SUCCESS_INDICATOR. For example:

:- pred string.contains_char(string, character).
:- mode string.contains_char(in, in) is semidet.

:- pragma foreign_proc("C",
    string.contains_char(Str::in, Ch::in),
    [will_not_call_mercury, promise_pure],
"
    SUCCESS_INDICATOR = (strchr(Str, Ch) != NULL);
").

SUCCESS_INDICATOR should not be used other than as the target of an assignment. (For example, it may be #defined to a register, so you should not try to take its address.) Procedures whose determinism indicates that they cannot fail should not access SUCCESS_INDICATOR.

Arguments whose mode is input will have their values set by the Mercury implementation on entry to the C code. If the procedure succeeds, the C code must set the values of all output arguments. If the procedure fails, the C code need only set SUCCESS_INDICATOR to false (zero).

The behaviour of a procedure defined using a ‘pragma foreign_proc’ declaration whose body contains a return statement is undefined.


16.10.1.5 Using pragma foreign_export for C

A ‘pragma foreign_export’ declaration for C has the form:

:- pragma foreign_export("C", MercuryMode, "C_Name").

For example,

:- pragma foreign_export("C", foo(in, in, out), "FOO").

For each Mercury module containing ‘pragma foreign_export’ declarations for C, the Mercury implementation will automatically create a header file for that module which declares a C function C_Name() for each of the ‘pragma foreign_export’ declarations. Each such C function is the C interface to the specified Mercury procedure.

The type signature of the C interface to a Mercury procedure is determined as follows. Mercury types are converted to C types according to the rules in C data passing conventions. Input arguments are passed by value. For output arguments, the caller must pass the address in which to store the result. If the Mercury procedure can fail, then its C interface function returns a truth value indicating success or failure. If the Mercury procedure is a Mercury function that cannot fail, and the function result has an output mode, then the C interface function will return the Mercury function result value. Otherwise the function result is appended as an extra argument. Arguments of type ‘io.state’ or ‘store.store(_)’ are not passed at all. (The reason for this is that these types represent mutable state, and in C modifications to mutable state are done via side effects, rather than argument passing.)

Calling polymorphically typed Mercury procedures from C is a little bit more difficult than calling ordinary (monomorphically typed) Mercury procedures. The simplest method is to just create monomorphic forwarding procedures that call the polymorphic procedures, and export them, rather than exporting the polymorphic procedures.

If you do export a polymorphically typed Mercury procedure, the compiler will prepend one ‘type_info’ argument to the parameter list of the C interface function for each distinct type variable in the Mercury procedure’s type signature. The caller must arrange to pass in appropriate ‘type_info’ values corresponding to the types of the other arguments passed. These ‘type_info’ arguments can be obtained using the Mercury ‘type_of’ function in the Mercury standard library module ‘type_desc’.

To use the C declarations produced see Using pragma foreign_decl for C.

Throwing an exception across the C interface is not supported. That is, if a Mercury procedure that is exported to C using ‘pragma foreign_export’ throws an exception which is not caught within that procedure, then you will get undefined behaviour.


16.10.1.6 Using pragma foreign_decl for C

Any macros, function prototypes, or other C declarations that are used in ‘foreign_code’, ‘foreign_type’ or ‘foreign_proc’ pragmas must be included using a ‘foreign_decl’ declaration of the form

:- pragma foreign_decl("C", HeaderCode).

HeaderCode can be a C ‘#include’ line, for example

:- pragma foreign_decl("C", "#include <math.h>")

or

:- pragma foreign_decl("C", "#include ""tcl.h""").

or it may contain any C declarations, for example

:- pragma foreign_decl("C", "
        extern int errno;
        #define SIZE 200
        struct Employee {
                char name[SIZE];
        };
        extern int bar;
        extern void foo(void);
").

Mercury automatically includes certain headers such as <stdlib.h>, but you should not rely on this, as the set of headers which Mercury automatically includes is subject to change.

If a Mercury predicate or function exported using a ‘pragma foreign_export’ declaration is to be used within a ‘:- pragma foreign_code’ or ‘:- pragma foreign_proc’ declaration the header file for the module containing the ‘pragma foreign_export’ declaration should be included using a ‘pragma foreign_import_module’ declaration, for example

:- pragma foreign_import_module("C", exporting_module).

16.10.1.7 Using pragma foreign_code for C

Definitions of C functions or global variables may be included using a declaration of the form

:- pragma foreign_code("C", Code).

For example,

:- pragma foreign_code("C", "
        int bar = 42;
        void foo(void) {}
").

Such code is copied verbatim into the generated C file.


16.10.1.8 Memory management for C

Passing pointers to dynamically-allocated memory from Mercury to code written in other languages, or vice versa, is in general implementation-dependent.

The current Mercury implementation supports two different methods of memory management: conservative garbage collection, or no garbage collection. The latter is suitable only for programs with very short running times (less than a second), which makes the former the standard method for almost all Mercury programs.

Conservative garbage collection makes inter-language calls simplest. Mercury uses the Boehm-Demers-Weiser conservative garbage collector, which we also call simply Boehm gc. This has its own set of functions for allocating memory blocks, such as ‘MR_GC_NEW’, which are documented in runtime/mercury_memory.h. Memory blocks allocated by these functions, either in C code generated by the Mercury compiler or in C code hand written by programmers, are automatically reclaimed when they are no longer referred to either from the stack, from global variables, or from other memory blocks allocated by Boehm gc functions. Note that these are the only places where Boehm gc looks for pointers to the blocks it has allocated. If the only pointers to such a block occur in other parts of memory, such as in memory blocks allocated by ‘malloc’, the Boehm collector won’t see them, and may collect the block prematurely. Programmers can avoid this either by not storing pointers to Boehm-allocated memory in malloc-allocated blocks, or by storing them e.g. on the stack as well.

Boehm gc recognizes pointers to the blocks it has allocated only if they point either to the start to the block, or to a byte in the first word of the block; pointers into the middle of a block beyond the first word won’t keep the block alive.

Pointers to Boehm-allocated memory blocks can be passed freely between Mercury and C code provided these restrictions are observed.

Note that the Boehm collector cannot and does not recover memory allocated by other methods, such as ‘malloc’.

When using no garbage collection, heap storage is reclaimed only on backtracking. This requires programmers to be careful not to retain pointers to memory on the Mercury heap after Mercury has backtracked to before the point where that memory was allocated. They must also avoid the use of the macros MR_list_empty() and MR_list_cons(). (The reason for this is that they may access Mercury’s ‘MR_hp’ register, which might not be valid in C code. Using them in the bodies of procedures defined using ‘pragma foreign_proc’ with ‘will_not_call_mercury’ would probably work, but we don’t advise it.) Instead, you can write Mercury functions to perform these actions and use ‘pragma foreign_export’ to access them from C. This alternative method also works with conservative garbage collection.

Future Mercury implementations may use non-conservative methods of garbage collection. For such implementations, it will be necessary to explicitly register pointers passed to C with the garbage collector. The mechanism for doing this has not yet been decided on. It would be desirable to provide a single memory management interface for use when interfacing with other languages that can work for all methods of memory management, but more implementation experience is needed before we can formulate such an interface.


16.10.1.9 Linking with C object files

A Mercury implementation should allow you to link with object files or libraries that were produced by compiling C code. The exact mechanism for linking with C object files is implementation-dependent. The following text describes how it is done for the Melbourne Mercury implementation.

To link an existing object file or archive of object files into your Mercury code, use the command line option ‘--link-object’. For example, the following will link the object file ‘my_function.o’ from the current directory when compiling the program ‘prog’:

mmc --link-object my_functions.o prog

The command line option ‘--library’ (or ‘-l’ for short) can be used to link an existing library into your Mercury code. For example, the following will link the library file libfancy_library.a, or perhaps the shared version libfancy_library.so, from the directory /usr/local/contrib/lib, when compiling the program ‘prog’:

mmc -R/usr/local/contrib/lib -L/usr/local/contrib/lib -lfancy_library prog

As illustrated by the example, the command line options ‘-R’, ‘-L’ and ‘-l’, have the same meaning as they do with the Unix linker.

For more information, see the “Libraries” chapter of the Mercury User’s Guide.


16.10.2 Interfacing with C#


16.10.2.1 Using pragma foreign_type for C#

A C# ‘pragma foreign_type’ declaration has the form:

:- pragma foreign_type("C#", MercuryTypeName, "C#-Type").

The C#-Type can be any accessible C# type.

The effect of this declaration is that Mercury values of type MercuryTypeName will be passed to and from C# foreign_procs as having type C#-Type.

Furthermore, any Mercury procedure exported with ‘pragma foreign_export’ will use C#-Type as the type for any parameters whose Mercury type is MercuryTypeName.


16.10.2.2 Using pragma foreign_enum for C#

Foreign enumeration values in C# must be a constant value expression which is a valid initializer within an enumeration of underlying type int.


16.10.2.3 Using pragma foreign_export_enum for C#

For C# the symbolic names generated by a ‘pragma foreign_export_enum’ must form valid C# identifiers. These identifiers are used as the names of static class members.

The default mapping used by ‘pragma foreign_export_enum’ declarations for C# is to use the Mercury constructor name as the base of the symbolic name. For example, the symbolic name for the Mercury constructor ‘foo’ would be foo.


16.10.2.4 Using pragma foreign_proc for C#

The C# code from C# ‘pragma foreign_proc’ declarations will be placed in the bodies of static member functions of an automatically generated C# class. Since such C# code will become part of a static member function, it must not refer to the this keyword. It may however refer to static member variables or static member functions declared with ‘pragma foreign_code’.

The input and output variables for a C# ‘pragma foreign_proc’ will have C# types corresponding to their Mercury types. The exact rules for mapping Mercury types to C# types are described in C# data passing conventions.

C# code in a pragma foreign_proc declaration for any procedure whose determinism indicates that it can fail must assign a value of type bool to the variable SUCCESS_INDICATOR. For example:

:- pred string.contains_char(string, character).
:- mode string.contains_char(in, in) is semidet.

:- pragma foreign_proc("C#",
    string.contains_char(Str::in, Ch::in),
    [will_not_call_mercury, promise_pure],
"
    SUCCESS_INDICATOR = (Str.IndexOf(Ch) != -1);
").

C# code for procedures whose determinism indicates that they cannot fail should not access SUCCESS_INDICATOR.

Arguments whose mode is input will have their values set by the Mercury implementation on entry to the C# code. If the procedure succeeds, the C# code must set the values of all output arguments. If the procedure fails, the C# code need only set SUCCESS_INDICATOR to false.


16.10.2.5 Using pragma foreign_export for C#

A ‘pragma foreign_export’ declaration for C# has the form:

:- pragma foreign_export("C#", MercuryMode, "C#_Name").

For example,

:- pragma foreign_export("C#", foo(in, in, out), "FOO").

The type signature of the C# interface to a Mercury procedure is as described in C# data passing conventions.

Calling polymorphically typed Mercury procedures from C# is a little bit more difficult than calling ordinary (monomorphically typed) Mercury procedures. The simplest method is to just create monomorphic forwarding procedures that call the polymorphic procedures, and export them, rather than exporting the polymorphic procedures.

If you do export a polymorphically typed Mercury procedure, the compiler will prepend one ‘type_info’ argument to the parameter list of the C# interface function for each distinct type variable in the Mercury procedure’s type signature. The caller must arrange to pass in appropriate ‘type_info’ values corresponding to the types of the other arguments passed. These ‘type_info’ arguments can be obtained using the Mercury ‘type_of’ function in the Mercury standard library module ‘type_desc’.


16.10.2.6 Using pragma foreign_decl for C#

pragma foreign_decl’ declarations for C# can be used to provide any top-level C# declarations (e.g. ‘using’ declarations or auxiliary class definitions) which are needed by C# code in ‘pragma foreign_proc’ declarations in that module.

For example:

:- pragma foreign_decl("C#", "
	using System;
").
:- pred hello(io.state::di, io.state::uo) is det.
:- pragma foreign_proc("C#",
     hello(_IO0::di, _IO::uo),
     [will_not_call_mercury, promise_pure],
"
    // here we can refer directly to Console rather than System.Console
    Console.WriteLine(""hello world"");
").

16.10.2.7 Using pragma foreign_code for C#

The C# code from ‘pragma foreign_proc’ declarations for C# will be placed in the bodies of static member functions of an automatically generated C# class. ‘pragma foreign_code’ can be used to define additional members of this automatically generated class, which can then be referenced by ‘pragma foreign_proc’ declarations for C# from that module.

For example:

:- pragma foreign_code("C#", "
    static int counter = 0;
").

:- impure pred incr_counter is det.
:- pragma foreign_proc("C#",
    incr_counter,
    [will_not_call_mercury], "
    counter++;
").

:- semipure func get_counter = int.
:- pragma foreign_proc("C#",
    get_counter = (Result::out),
    [will_not_call_mercury, promise_semipure],
"
    Result = counter;
").

16.10.3 Interfacing with Java


16.10.3.1 Using pragma foreign_type for Java

A Java ‘pragma foreign_type’ declaration has the form:

:- pragma foreign_type("Java", MercuryTypeName, "JavaType").

The JavaType can be any accessible Java type.

The effect of this declaration is that Mercury values of type MercuryTypeName will be passed to and from Java foreign_procs as having type JavaType.

Furthermore, any Mercury procedure exported with ‘pragma foreign_export’ will use JavaType as the type for any parameters whose Mercury type is MercuryTypeName.


16.10.3.2 Using pragma foreign_enum for Java

pragma foreign_enum’ is currently not supported for Java.


16.10.3.3 Using pragma foreign_export_enum for Java

For Java the symbolic names generated by a ‘pragma foreign_export_enum’ must form valid Java identifiers. These identifiers are used as the names of static class members which are assigned instances of the enumeration class.

The equals method should be used for equality testing of enumeration values in Java code.

The default mapping used by ‘pragma foreign_export_enum’ declarations for Java is to use the Mercury constructor name as the base of the symbolic name. For example, the symbolic name for the Mercury constructor ‘foo’ would be foo.


16.10.3.4 Using pragma foreign_proc for Java

The Java code from Java ‘pragma foreign_proc’ declarations will be placed in the bodies of static member functions of an automatically generated Java class. Since such Java code will become part of a static member function, it must not refer to the this keyword. It may however refer to static member variables or static member functions declared with ‘pragma foreign_code’.

The input and output variables for a Java ‘pragma foreign_proc’ will have Java types corresponding to their Mercury types. The exact rules for mapping Mercury types to Java types are described in Java data passing conventions.

The Java code in a pragma foreign_proc declaration for a procedure whose determinism indicates that it can fail must assign a value of type boolean to the variable SUCCESS_INDICATOR. For example:

:- pred string.contains_char(string, character).
:- mode string.contains_char(in, in) is semidet.

:- pragma foreign_proc("Java",
    string.contains_char(Str::in, Ch::in),
    [will_not_call_mercury, promise_pure],
"
    SUCCESS_INDICATOR = (Str.IndexOf(Ch) != -1);
").

Java code for procedures whose determinism indicates that they cannot fail should not refer to the SUCCESS_INDICATOR variable.

Arguments whose mode is input will have their values set by the Mercury implementation on entry to the Java code. With our current implementation, the Java code must set the values of all output variables, even if the procedure fails (i.e. sets the SUCCESS_INDICATOR variable to false).


16.10.3.5 Using pragma foreign_export for Java

A ‘pragma foreign_export’ declaration for Java has the form:

:- pragma foreign_export("Java", MercuryMode, "Java_Name").

For example,

:- pragma foreign_export("Java", foo(in, in, out), "FOO").

The type signature of the Java interface to a Mercury procedure is as described in Java data passing conventions.

Calling polymorphically typed Mercury procedures from Java is a little bit more difficult than calling ordinary (monomorphically typed) Mercury procedures. The simplest method is to just create monomorphic forwarding procedures that call the polymorphic procedures, and export them, rather than exporting the polymorphic procedures.

If you do export a polymorphically typed Mercury procedure, the compiler will prepend one ‘type_info’ argument to the parameter list of the Java interface function for each distinct type variable in the Mercury procedure’s type signature. The caller must arrange to pass in appropriate ‘type_info’ values corresponding to the types of the other arguments passed. These ‘type_info’ arguments can be obtained using the Mercury ‘type_of’ function in the Mercury standard library module ‘type_desc’.


16.10.3.6 Using pragma foreign_decl for Java

pragma foreign_decl’ declarations for Java can be used to provide any top-level Java declarations (e.g. ‘import’ declarations or auxiliary class definitions) which are needed by Java code in ‘pragma foreign_proc’ declarations in that module.

For example:

:- pragma foreign_decl("Java", "
import javax.swing.*;
import java.awt.*;

class MyApplet extends JApplet {
    public void init() {
        JLabel label = new JLabel(""Hello, world"");
        label.setHorizontalAlignment(JLabel.CENTER);
        getContentPane().add(label);
    }
}
").
:- pred hello(io.state::di, io.state::uo) is det.
:- pragma foreign_proc("Java",
    hello(_IO0::di, _IO::uo),
    [will_not_call_mercury],
"
    MyApplet app = new MyApplet();
    // …
").

16.10.3.7 Using pragma foreign_code for Java

The Java code from ‘pragma foreign_proc’ declarations for Java will be placed in the bodies of static member functions of an automatically generated Java class. ‘pragma foreign_code’ can be used to define additional members of this automatically generated class, which can then be referenced by ‘pragma foreign_proc’ declarations for Java from that module.

For example:

:- pragma foreign_code("Java", "
    static int counter = 0;
").

:- impure pred incr_counter is det.
:- pragma foreign_proc("Java",
    incr_counter,
    [will_not_call_mercury],
"
    counter++;
").

:- semipure func get_counter = int.
:- pragma foreign_proc("Java",
    get_counter = (Result::out),
    [will_not_call_mercury, promise_semipure],
"
    Result = counter;
").

Previous: Using pragma foreign_decl for Java, Up: Interfacing with Java   [Contents]