Next: , Previous: Data passing conventions, Up: Foreign language interface


14.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_code’ 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 and Erlang backends support this variant of the ‘pragma foreign_decl’ declaration.

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 sub-modules. They are not visible to the foreign code in ‘pragma foreign_code’ or ‘pragma foreign_proc’ declarations in any other module. They can be made visible 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.

A cycle of ‘pragma foreign_import_module’, where the language is ‘"C#"’ or ‘"Java"’, is not permitted.

Note that the Melbourne Mercury implementation often implicitly inserts ‘pragma foreign_import_module’ declarations but programmers should not write code that depends upon this behaviour; ‘pragma foreign_import_module’ declarations should always be explicitly included if needed.