[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',
e.g.
:- 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