this post was submitted on 29 Dec 2023
14 points (100.0% liked)

programming

174 readers
1 users here now

  1. Post about programming, interesting repos, learning to program, etc. Let's try to keep free software posts in the c/libre comm unless the post is about the programming/is to the repo.

  2. Do not doxx yourself by posting a repo that is yours and in any way leads to your personally identifying information. Use reports if necessary to alert mods to a potential doxxing.

  3. Be kind, keep struggle sessions focused on the topic of programming.

founded 11 months ago
MODERATORS
top 5 comments
sorted by: hot top controversial new old
[–] [email protected] 5 points 10 months ago (1 children)

I guess, I shouldn't have been surprised to be reading C code in this blog post, but man, even the 'clean' example has quite a bit of cruft, when looking at it from modern languages.

Like, this is the amount of ceremony I consider necessary (pseudo-code):

tracing::listen<ContextSwitch>(event -> {
  //process ContextSwitch event here
})
[–] [email protected] 4 points 10 months ago (1 children)

It's pretty uncommon for low-level system APIs to use callbacks in that way. Think about it: every time the kernel wants to notify the user of an event, it would have to call a function in userspace... but there are a few problems with that. For starters: which thread is it calling from? The user process isn't going to have stack mappings and whatnot set up for an arbitrary kernel thread. And if we set that aside for the time being, in order to actually run the callback, you'd have to make a context switch from kernel to user mode as well, for each event.

The kind of API shown in the example is much more common: userspace allocatesa buffer, makes a syscall to request the kernel to copy queued events into the buffer until it fills up or no more events are pending, and then iterate over them again in userspace. A higher-level userspace library might hide this away behind a simplified interface with a callback function, but somewhere down the abstraction hierarchy it's almost certainly going to end up looking something like this.

[–] [email protected] 1 points 10 months ago

Ah, good point. Yeah, in my mind, there was a thin wrapper library to allocate that buffer and such. Guess, we can't have that for the actual exposed interface.

I was also thinking, having to pass the size of the buffer and the buffer pointer separately, is just another C-ism, but that does make sense here then, too, because it's not implicitly relying on the memory layout of some List/Vec/whatever type.
Similarly, ETWGetEvents can only return a number of events, because it can't return a List/Vec/whatever.

Interesting perspective. And kind of weird to now be on-board with this API design, while also thinking I'm not touching that without a wrapper.

Maybe in a few decades, the Rust ABI will have stabilized and become ubiquitous enough, that we can have at least some of these amenities. But chances are, Rust will look quite antique by then, too, and we're back to writing wrappers anyways. 🙃

[–] [email protected] 3 points 10 months ago

Haven't read yet, but I have to deal with ESRI's python API at work a lot and I want to kill them.

The objects created by a function have different attribute names and required data types than the functions that create them........

[–] [email protected] 2 points 10 months ago

My least favorite API is the CFITSIO library for working with FITS format data files. That shit was written in Fortran way back in the day and every decent library to touch it is just a wrapper around that. And it sucks. But this nonsense might be worse honestly.