[mercury-users] Mercury and C
Fergus Henderson
fjh at cs.mu.OZ.AU
Tue Nov 12 20:31:20 AEDT 2002
On 12-Nov-2002, Ralph Becket <rafe at cs.mu.OZ.AU> wrote:
> Drirr C., Monday, 11 November 2002:
> > I'm writing a program using Mercury and C, however I haven't been able to
> > return a string from the c function.
> >
> > I have something like this:
> >
> > :- pred buildPoly(int::in, int::in, int::in, int::in, string::out) is det.
> > ...
> > :- pragma c_code(buildPoly(VARS::in,TERMS::in,NEG::in,SEED::in,OUT::out),
> > [may_call_mercury], "buildPoly(VARS,TERMS,NEG,SEED,OUT);").
> >
> > And then something like this:
> >
> > void buildPoly(MR_Integer variables, MR_Integer terms, MR_Integer
> > negations, MR_Integer seed, MR_Word result) {
> > ...
> > buffer = (char*)malloc(...);
> > ...
> > *((char **)result) = buffer;
> > }
>
> According to "Passing Data to and from C" in the Reference Manual
> http://www.mercury.cs.mu.oz.au/information/doc-latest/reference_manual_14.html#SEC126
> we have
> typedef MR_Char *MR_String;
Right.
> Also, we have "For output arguments, the Mercury implementation will
> pass to the C function an address in which to store the result."
That statement only applies to C functions imported using "pragma import"
(or exported using "pragma export"), not to "pragma c_code", for which
you just have a C code fragment, not a C function.
If you are using "pragma c_code", then you just assign to the output variables.
:- pragma c_code(buildPoly(VARS::in,TERMS::in,NEG::in,SEED::in,OUT::out),
[may_call_mercury], "OUT = buildPoly(VARS,TERMS,NEG,SEED);").
^^^^^^
If you want, you can do these assignments indirectly, by passing the
addresses of the output arguments to a function, but if so, you need
to explicitly take the address:
:- pragma c_code(buildPoly(VARS::in,TERMS::in,NEG::in,SEED::in,OUT::out),
[may_call_mercury], "buildPoly(VARS,TERMS,NEG,SEED,&OUT);").
^
However, if all you are doing in the `pragma c_code' is calling a
C function, then generally it's better to use `pragma import',
since that is more concise:
:- pragma import(buildPoly(in,in,in,in,out), [may_call_mercury],
"buildPoly").
That, together with Ralph's suggestion about using `MR_String *'
rather than `MR_Word', should solve your problem. The suggestion
about using MR_GC_malloc() rather than malloc() is also a good idea;
it avoids a potential memory leak.
Putting all these together:
:- pragma import(buildPoly(in,in,in,in,out), [may_call_mercury],
"buildPoly").
:- pragma c_header_code("
void
buildPoly(MR_Integer variables, MR_Integer terms, MR_Integer negations,
MR_Integer seed, MR_String *result);
").
:- pragma c_code("
void
buildPoly(MR_Integer variables, MR_Integer terms, MR_Integer negations,
MR_Integer seed, MR_String *result)
{
char *buffer;
...
buffer = (char*)MR_GC_malloc(...);
...
*result = buffer;
}
").
Or alternatively, you can write the C code inline, rather than
putting it in a separate C function:
:- pragma c_code(buildPoly(VARS::in,TERMS::in,NEG::in,SEED::in,OUT::out),
[may_call_mercury],
"
char *buffer;
...
buffer = (char*)MR_GC_malloc(...);
...
OUT = buffer;
").
--
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