[m-users.] Ignoring !IO in an FFI binding, aceptable or hideously bad?
Sean Charles (emacstheviking)
objitsu at gmail.com
Tue Feb 18 05:33:13 AEDT 2025
Mark, Zoltan, thanksz for your time.
Mark, your solution seems a good one for me.
I also later saw thaqt as the module mutable initialisation occursa before I call my explicit lo\ad, that in fact it was never going to work as I had though anyway!
Zoltan, case "A" is me: one time init. of fonts, for lifetime of application then unload and quit on user command.
I do recall at least one or two instances in the manuals about the penalty for "lying to the compiler" !
So, I shall use the same techniques I used inmy POC video space shooter game and make sure I never lie to the compiler, after all, it's got my back!
Thanks all.
Happy belated 2025 too.
My 6th year begind as a Mercury user IIRC.
> On 16 Feb 2025, at 11:38, Sean Charles (emacstheviking) <objitsu at gmail.com> wrote:
>
> Hello,
>
> I have a not insignificant binding to Raylib now, and during a recent bit of experimental coding, I decided on trying a different way to manage assets, in this case fonts.
>
> :- import_module raylib.
> :- type font_state
> ---> font_state(
> default :: rfont,
> main :: rfont
> ).
> :- mutable(fstate, maybe(font_state), no, ground, [untrailed]).
>
> I am forced to initialise to `no` because until the Raylib library is initialised, loading fonts doesn't work, however, I have experimented with a second version of load_font in my binding that does not use !IO:
>
> 1162
> 1163 :- pragma foreign_proc(
> 1164 "C", load_font2(FontName::in, Out::out),
> 1165 [ promise_pure, will_not_call_mercury, will_not_throw_exception
> 1166 , will_not_modify_trail, thread_safe, does_not_affect_liveness
> 1167 ],
> 1168 "
> 1169 void* p = MR_GC_malloc_uncollectable(sizeof(Font));
> 1170 Out = p;
> 1171 Font font = LoadFont(FontName);
> 1172 memcpy(p, &font, sizeof(Font));
> 1173 ").
>
> They both work, and it means that I can now load fonts by adding an initialise call to the module and then loading fonts without having an !IO context. I think I might change the mutable to be a `univ` on the grounds that after module initialisation, I know it will contain a fully populated `font_state`. I envisaged the new call looking something like this:
>
> :- mutable(fstate, font_state,
> font_state(
> load_default_font,
> load_a_font("path/to/main/font.ttf")
> ),
> ground,
> [untrailed]
> ).
>
> ...but I would have to write a function shim as well
>
> :- func load_a_font(string::in) = (rfont::out) is det.
> load_a_font(Path) = F :-
> load_font(Path, F). % No !IO context!
>
>
> Sorry for rambling thus far, but my question is this: if I remove "!IO" from all of my binding to Raylib, what price might I pay in my code? The Raylib environment is hidden inside the library, any allocations it does are not known to Mercury, so what possible problems might I face if Mercury sees the same bunch of `det` calls but they don't need IO state in and out? Is that "lying" to Mercury in such a way as it could cause subtle issues, I am writing an IDE so it's a non-trivial project.
>
> Or should I only remove IO from the asset loading functions?
>
> I am just looking for ideas / advice etc on how to proceed such that I don;t inadvertently cause myself issues by lying to the compiler.
>
> Thanks,
> Sean.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20250217/3d8d3c24/attachment-0001.html>
More information about the users
mailing list