[mercury-users] Calling Mercury from C

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Jul 11 15:44:54 AEST 2003

On 11-Jul-2003, Michael Day <mikeday at yeslogic.com> wrote:
> > In general the representation of Mercury closures can vary depending on
> > the Mercury compiler options -- they are represented differently in
> > different grades.
> Okay, so the export mechanism can be used as a grade-independent method of 
> calling Mercury closures from C.
> One question though, what about type classes? I am currently calling
> polymorphically typed predicates from C by passing an explicit type_info
> and everything works very nicely. However the reference manual does not
> appear to describe how to call an exported Mercury function that is
> polymorphically typed with type class constraints.
> Presumably passing a method dictionary?

Internally, yes, that's the way it works.  However, we don't provide any
user-accessible ways of constructing method dictionaries, and again the
representation of method dictionaries may be different for different grades.

If the procedure that you want to call from C is polymorphically typed
with type class constraints, and you want to call it with a particular
list of arguments whose (monomorphic) types are known statically, then
the simplest way of doing this is to export to C a monomorphic Mercury
forwarding procedure that just calls the polymorphically typed procedure.

If you want to call a constrained polymorphically typed procedure
using arguments whose types are not known statically, it gets a bit more
complicated.  Probably the best way to do this is to wrap up the class
dictionaries using an existential type, e.g.

	:- typeclass fooable(T) where [ func my_method(T) = string ].

	:- type foo ---> some [T] (mkfoo(T) <= fooable(T)).

You can export functions to C that will construct values of this type `foo',

	:- instance fooable(int) where [ my_method(_) = "whatever" ].

	:- func make_fooable_int(int) = foo.
	make_fooable_int(X) = 'new mkfoo'(X).

	:- pragam export(make_fooable_int(in) = out, "make_fooable_int").

Then you can call make_fooable_int() from C code to give you a method
dictionary for the fooable type class, wrapped up in a value of type foo.
You can then pass around values of this type `foo' through C code and
back to Mercury code again.  Once you're in Mercury code, you can unwrap
the existentially quantified type, and call the class methods.

	:- func call_my_method(foo) = string.
	:- pragma export(call_my_method(in) = out, "call_my_method").
	call_my_method(mkfoo(X)) = my_method(X).

Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe

More information about the users mailing list