[m-users.] Refactoring Mercury/C FFi code

emacstheviking objitsu at gmail.com
Mon Jul 15 08:08:13 AEST 2019


I apologise for the long code at the end but I felt it was necessary to
fully ask my question.
My SDL2 wrapper is progressing nicely, I can draw lines, rectangles, filled
rectangles and load and render textures so far all without issue
but....boiler plate.

For example. SDL_RenderCopy can be passed either a NULL or an &SDL_Rect to
indicate the source and destination rectangles from the source texture and
destination respectively allowing sprite sheets etc or image scaling to be
performed.

However, with my limited knowledge I have only so far produced the code
shown at the end and to be perfectly honest I think it stinks and is
riddled with boiler plate. My question then is what would be "the best way"
to handle this case. With two rectangles I have had to create four
predicates, with three it would be 8 etc etc and it feels like there is a
better way.

I have seen code that creates mercury predaites then exportds them so they
can be called from "C" but I don't yet fully understand that as the code I
read (https://github.com/FlyingJester/SDL2.m/blob/master/sdl2.m) is a bit
over my head for the moment!
This also comes back to my previous question about being able to use
SDL_Rect as a foreign type etc. From what I have learned so far I know that
parameters are passed in as MR_Word sized values so would it be safe for
example to cast an sdl_rect() declared as:


*:- type sdl_rect ---> sdl_rect(x::int, y::int, w::int, h::int).*






*typedef struct SDL_Rect{    int x, y;    int w, h;} SDL_Rect;*

to an SDL_Rect which has the same size and shape?!?!?!?! These are thing
things holding me back right now.

Thanks,
Sean.

---> the code


*:- pred sdl_rendercopy(sdl_renderer::in, sdl_texture::in,
maybe(sdl_rect)::in, maybe(sdl_rect)::in, io::di, io::uo) is det.*

    % SDL_RenderCopy
sdl_rendercopy(Rnd, Tex, no, no, !IO) :-
    sdl_rendercopy_no_no(Rnd, Tex, !IO).

sdl_rendercopy(Rnd, Tex, no, yes(Dst), !IO) :-
    sdl_rendercopy_no_yes(Rnd, Tex, Dst^x, Dst^y, Dst^w, Dst^h, !IO).

sdl_rendercopy(Rnd, Tex, yes(Src), no, !IO) :-
    sdl_rendercopy_yes_no(Rnd, Tex, Src^x, Src^y, Src^w, Src^h, !IO).

sdl_rendercopy(Rnd, Tex, yes(Src), yes(Dst), !IO) :-
    sdl_rendercopy_yes_yes(Rnd, Tex,
        Src^x, Src^y, Src^w, Src^h,
        Dst^x, Dst^y, Dst^w, Dst^h,
        !IO).


*:- pred sdl_rendercopy_no_no(sdl_renderer::in, sdl_texture::in, io::di,
io::uo) is det.:*- pragma foreign_proc("C",
    sdl_rendercopy_no_no(Rnd::in, Tex::in, _IO0::di, _IO::uo),
    [promise_pure,will_not_call_mercury,does_not_affect_liveness],
    "SDL_RenderCopy(Rnd, Tex, NULL, NULL);").


*:- pred sdl_rendercopy_no_yes(sdl_renderer::in, sdl_texture::in, int::in,
int::in, int::in, int::in, io::di, io::uo) is det.*:- pragma
foreign_proc("C",
    sdl_rendercopy_no_yes(Rnd::in, Tex::in, X::in, Y::in, W::in, H::in,
_IO0::di, _IO::uo),
    [promise_pure,will_not_call_mercury,does_not_affect_liveness],
    "SDL_Rect rDst;
    rDst.x = (Uint32)X;
    rDst.y = (Uint32)Y;
    rDst.w = (Uint32)W;
    rDst.h = (Uint32)H;
    SDL_RenderCopy(Rnd, Tex, NULL, &rDst);").


*:- pred sdl_rendercopy_yes_no(sdl_renderer::in, sdl_texture::in, int::in,
int::in, int::in, int::in, io::di, io::uo) is det.*:- pragma
foreign_proc("C",
    sdl_rendercopy_yes_no(Rnd::in, Tex::in, X::in, Y::in, W::in, H::in,
_IO0::di, _IO::uo),
    [promise_pure,will_not_call_mercury,does_not_affect_liveness],
    "SDL_Rect rSrc;
    rSrc.x = (Uint32)X;
    rSrc.y = (Uint32)Y;
    rSrc.w = (Uint32)W;
    rSrc.h = (Uint32)H;
    SDL_RenderCopy(Rnd, Tex, &rSrc, NULL);").


*:- pred sdl_rendercopy_yes_yes(sdl_renderer::in, sdl_texture::in, int::in,
int::in, int::in, int::in,int::in, int::in, int::in, int::in, io::di,
io::uo) is det.*:- pragma foreign_proc("C",
    sdl_rendercopy_yes_yes(Rnd::in, Tex::in,
        XS::in, YS::in, WS::in, HS::in,
        XD::in, YD::in, WD::in, HD::in,
        _IO0::di, _IO::uo),
    [promise_pure,will_not_call_mercury,does_not_affect_liveness],
    "SDL_Rect rDst;
    SDL_Rect rSrc;
    rSrc.x = (Uint32)XS;
    rSrc.y = (Uint32)YS;
    rSrc.w = (Uint32)WS;
    rSrc.h = (Uint32)HS;
    rDst.x = (Uint32)XD;
    rDst.y = (Uint32)YD;
    rDst.w = (Uint32)WD;
    rDst.h = (Uint32)HD;
    SDL_RenderCopy(Rnd, Tex, &rSrc, &rDst);").
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20190714/35c053f6/attachment-0001.html>


More information about the users mailing list