[m-users.] Calling type constructors from C
Julien Fischer
jfischer at opturion.com
Wed Jul 10 19:26:18 AEST 2019
Hi Sean,
On Wed, 10 Jul 2019, emacstheviking wrote:
> Any clues in the documentation as to where I can find out how to do
> this? I've looked (and failed) to figure out how to call "maybe(T)"
You don't call maybe(T), in this case you are attempting to construct
it.
> from C, basically I have the result of calling a C function that
> reutns NULL or a window pointer:
> SDL_WIndow *w = SDL_CreateWindow(...);
>
> and I want the pred to return maybe(sdl_window) where so in my main code I can switch on the result blah blah
>
> sdl_creatwindow(..., MW, ..., !IO),
> (
> MW = yes(Wnd),
> % start my app
> ;
> MW = no,
> % fail path
> ),
>
>
> :- type sdl_window.
> :- pragma foreign_type("C", sdl_window, "SDL_Window *", [can_pass_as_mercury_type]).
>
> It's just knowing what the "way" is?!?!
The two usual approaches here would be:
1. Export a Mercury function to C that wraps the result of
SDL_CreatWindow and call that from within the foreign_proc for
sdl_createwindow. E.g.
:- pragma foreign_export("C", maybe_yes_window(in) = out,
"MER_maybe_yes_window").
:- func maybe_yes_window(sdl_window) = maybe(sdl_window).
maybe_yes_window(W) = yes(W).
:- pragma foreign_export("C", maybe_no_window = out,
"MER_maybe_no_window").
:- func maybe_no_window = maybe(sdl_window).
maybe_no_window = no.
:- pragma foreign_proc("C",
sdl_createwindow(... MW::in, ... _IO0::di, IO::uo),
[will_call_mercury, promise_pure],
"
SDL_Window *w = <<create the window>>;
if (w == null) {
MW = MER_maybe_no_window();
} else {
MW = MER_maybe_yes_window(w);
}
").
NOTE: since sdl_createwindow will make calls back to Mercury the
'will_call_mercury' foreign code attribute must be set on the foreign
proc.
2. Return an additional flag indicating if the window pointer is null or
not.
sdl_createwindow(..., MW, ..., !IO) :-
do_createwindow(..., IsNull, W, !IO),
(
IsNull = no,
MW = yes(W)
;
IsNull = yes,
MW = no
).
:- pred do_createwindow(..., bool::out, sdl_window::out,
io::di, io::uo) is det.
:- pragma foreign_proc("C",
do_create_window(..., IsNull::out, W::out, _IO0::, _IO::uo),
[will_not_call_mercury, promise_pure],
"
W = <<create the window>>;
IsNull = (W == null) ? MR_YES : MR_NO;
").
Julien.
More information about the users
mailing list