I'm writing on an SDR software with a friend (based on radiorust
) and I'm looking for a crate which allows direct access to pixels in a window (or some sort of canvas). Using the sdl2
crate, we ran (non-reproducibly under some strange conditions, which didn't really relate to the failing call) into a segmentation fault:
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `target/release/receiver'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007fb951e016be in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
[Current thread is 1 (Thread 0x7fb950904d00 (LWP 188437))]
(gdb)
(gdb) bt
#0 0x00007fb951e016be in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#1 0x00007fb951df0486 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#2 0x00007fb951e25f63 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#3 0x00007fb951db9da0 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#4 0x000055a3eae349d4 in sdl2::render::InternalTexture::update ()
Not sure if it's sdl2
's fault. We didn't use any unsafe
at all, so I understand this shouldn't happen. However, there was also the soapysdr
crate involved in the binary, which uses the underlying SoapySDR library, so there's C(++) code involved also (including drivers) which could have caused UB.
Nonetheless, I'm not sure if perhaps sdl2
is more likely to be the cause of the problems (due to the backtrace as well as because of other bugs causing segfaults).
We wondered, if there's a lightweight alternative to sdl2
. We don't really need widgets, but rendering text would be a requirement. There is flo_draw
(version 0.3 on crates.io, a version 0.4 on GitHub, not sure why it's not updated on crates.io?), but it has a weird interface where you have to pass an Arc<Vec<u8>>
(which means I have to do allocations) every time I want to update texture pixels. I didn't find any more suitable interface (yet), which allows mutably accessing the pixels.
Looking for other alternatives, I also found miniquad
, which has a promising claim:
Miniquad is a manifestation of a dream in a world where we do not need a deep dependencies tree and thousands lines of code to draw things with a computer.
Miniquad aims to provide a graphics abstraction that works the same way on any platform with a GPU, being as light weight as possible while covering as many machines as possible.
But running the example(s) from miniquad
on my FreeBSD system just gives this:
% cargo run --example quad
warning: unused variable: `conf`
--> src/lib.rs:180:17
|
180 | pub fn start<F>(conf: conf::Conf, f: F)
| ^^^^ help: if this is intentional, prefix it with an underscore: `_conf`
|
= note: `#[warn(unused_variables)]` on by default
warning: unused variable: `f`
--> src/lib.rs:180:35
|
180 | pub fn start<F>(conf: conf::Conf, f: F)
| ^ help: if this is intentional, prefix it with an underscore: `_f`
warning: associated function `with_display` is never used
--> src/lib.rs:43:19
|
43 | pub(crate) fn with_display(&mut self, display: &mut dyn NativeDisplay) -> &mut Context {
| ^^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
warning: `miniquad` (lib) generated 3 warnings
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/examples/quad`
And then I get back to the shell. The program just exits (with exit code 0
) without doing anything. I haven't tested it on Linux yet.
So what should I do? Track down the segmentation fault that's supposedly caused by sdl2
? Use flo_draw
? Invest time trying to find out why miniquad
doesn't work and whether it's suitable?
Or is there any out-of-the-box solution that does what I need?
P.S.: Another issue we had with sdl2
was that the way it handles lifetimes made it impossible to put all involved data structures of the user interface into a struct, because it would have required self-referential structs. It was really difficult to handle. Plus, in the documentation sentences like:
A texture can only be used by the Canvas it was originally created from, it is undefined behavior otherwise.
Do they refer to unsafe
methods? And which ones? Or does this mean the crate is unsound by design?
I also looked into the gtk4
crate, which could maybe(?) used with "cairo" (which crate?) to draw on it, but documentation and ergonomics don't seem to be nice. I had a look at the documentation:
Simple GtkDrawingArea usage
The following code is in c
static void draw_function (GtkDrawingArea *area, …
How am I supposed to learn how to draw on it using Rust? I feel like gtk4
is only usable if you are a full-fledged GTK programmer having years of experience using it in C.
Why is this so difficult? Isn't there an easier way?