[m-users.] Ignoring !IO in an FFI binding, aceptable or hideously bad?
Sean Charles (emacstheviking)
objitsu at gmail.com
Sun Feb 16 22:38:48 AEDT 2025
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/20250216/30858000/attachment.html>
More information about the users
mailing list