[m-users.] Dealing with lists of enums as bitflags in C
Julien Fischer
jfischer at opturion.com
Tue Jul 9 12:23:53 AEST 2019
Hi,
On Mon, 8 Jul 2019, emacstheviking wrote:
> I have been hacking a good hour or two and not really made much
> progress for something that I thought would have been simpler, but.
> Ignorance!!
> In my SDL2 wrapper I have a list of types that correspond to the
> various window creation flags, I am passing them as a list as that's
> the nicest way of doing it I think,
>
> sdl_createwindow("Test", 100, 100, 640, 480, [resizable, shown], !IO)
>
> The types are declared as foreign enums in the usual way :-
> :- type window_flag
> ---> fullscreen ; opengl ; shown ; resizable ..... (elided)
>
> :- pragma foreign_enum("C", window_flag/0, [
> fullscreen - "SDL_WINDOW_FULLSCREEN",
> opengl - "SDL_WINDOW_OPENGL",
> shown - "SDL_WINDOW_SHOWN",
> resizable - "SDL_WINDOW_RESIZABLE",
> :...(elided)
> ]).
>
> By using the --make-target option to poke at the generated code I can
> see that it comes into the C code as MR_Word, not MR_Word*thought and
> then I tracked down the definitions of the MR_is_list_empty macros etc
> and realised pretty quickly that there is no "MR_get_next" as it
> should be as simple as pointer arithmetic but so far it has escaped my
> best efforts. I have seen that the array is composed as a static array
> of values from the MR_TAG_COMMON but I lost the trail at that point.
If you haven't done so already, have a look at
<http://mercurylang.org/information/doc-latest/mercury_ref/C-data-passing-conventions.html#C-data-passing-conventions>
since it lists all of the list manipulation macros.
> Here is my code:
>
> :- pred sdl_createwindow(string::in, int::in, int::in, int::in, int::in, list(window_flag)::in, io::di, io::uo) is det.
> :- pragma foreign_proc("C",
> sdl_createwindow(Title::in, X::in, Y::in, W::in, H::in, Flags::in, _IO0::di, _IO::uo),
> [promise_pure,will_not_call_mercury,does_not_affect_liveness],
> "
> Uint32 flags = 0;
> if (Flags) {
> MR_Word* flagPtr = &Flags;
> while(!MR_list_is_empty(*flagPtr)) {
> Uint32 f = MR_list_head(*flagPtr);
> flags |= f;
> printf(""FLAGS: %u\\n"", flags);
> flagPtr++;
> }
> }
> SDL_Window* wnd = SDL_CreateWindow(Title, X, Y, W, H, flags);
> ").
>
> I just want to iterate the list of types and OR together the final bit
> flag uint32 value and get on with creating the window. This is
> something that is going to crop up again and again in various parts of
> the library. I am pretty sure I will figure out immediately hitting
> send.....
I started writing an SDL binding many years ago and as the above kind of
thing occurs in a number of places I defined the following utility
function in C to handle the conversion of lists of of flags:
:- pragma foreign_code("C", "
Uint32
MSDL_list_to_flags(MR_Word list)
{
Uint32 flags = 0;
while (!MR_list_is_empty(list)) {
flags |= (Uint32) MR_list_head(list);
list = MR_list_tail(list);
}
return flags;
}
").
Julien.
More information about the users
mailing list