Re:Neat Rust Tricks: Passing Closures to C
by Diggsey on Monday November 25, 2019 @04:31PM
(#21633029)
It doesn't. This is just showing the normal way that callbacks are implemented in vanilla C and how you would make that programming pattern interoperate with Rust closures. Neither one relies on the compiler trickery/runtime code generation described in the earlier article.
Re:Neat Rust Tricks: Passing Closures to C
by zozbot234 on Monday November 25, 2019 @04:36PM
(#21633069)
The executable stack trick is only required if you want to implement closures that can be called as if they were plain C functions, with only a function pointer and no extra (void *) argument.
Re:Neat Rust Tricks: Passing Closures to C
by rabidferret on Monday November 25, 2019 @04:36PM
(#21633073)
It doesn't relate to it at all. The issues around linking to problematic object files mentioned in that article will apply to Rust as well, but that's unrelated to the subject of this article, it's a property of the linker you're using and the toolchain used to compile whatever C dependencies you have
Re:Neat Rust Tricks: Passing Closures to C
by richardwhiuk on Monday November 25, 2019 @04:30PM
(#21633025)
The problems there don't apply I believe because Rust closures don't require an executable stack.
Re:Neat Rust Tricks: Passing Closures to C
by mmastrac on Monday November 25, 2019 @04:42PM
(#21633130)
That's correct - a Rust closure generally [1] can't be converted to a function pointer as it requires both code and state.
The whole point of jgtrosh's link is that there is a way to hide data behind a function pointer, so Rust could convert any closure to a function pointer. But it requires writable-and-executable memory, so it's a pretty bad idea (in GCC's implementation, that memory is on the stack, which is an extra bad idea, but i don't think it needs to be).
Re:Neat Rust Tricks: Passing Closures to C
by mmastrac on Monday November 25, 2019 @05:02PM
(#21633295)
Definitely.
Technically this can also be done via static code trampolines that are mmap'd as well [1]. That approach has been used on iOS in the past to turn blocks into raw function pointers.
If you have a platform that allows W+X on code (yikes!), you can do [2] as well.
[1] https://github.com/plausiblelabs/plblockimp/blob/master/Sour... [2] https://www.mikeash.com/pyblog/friday-qa-2010-02-12-trampoli...
Re:Neat Rust Tricks: Passing Closures to C
by rabidferret on Monday November 25, 2019 @06:23PM
(#21633988)
Anything that doesn't require W+X would need an entire page allocated per closure, wouldn't it?
Re:Neat Rust Tricks: Passing Closures to C
by devit on Monday November 25, 2019 @07:58PM
(#21634706)
No, you can of course allocate W+X pages from the OS and put multiple closures in them using a standard userspace memory allocator.
Or if the OS doesn't support W+X allocation at all, then you can have a bunch of tightly packed pregenerated trampolines in the binary.
Re:Neat Rust Tricks: Passing Closures to C
by saagarjha on Monday November 25, 2019 @08:26PM
(#21634861)
Right, this is how Objective-C's implementation works, except it keeps around one page of trampolines and remaps that around when necessary to be able to "create" more trampolines on the fly, I believe.
Re:Neat Rust Tricks: Passing Closures to C
by a1369209993 on Monday November 25, 2019 @10:58PM
(#21635551)
Nope! You'd do something to the effect of:
clo_code:
4C8B1501100000 mov r10 [rel clo_code+0x1008]
FF25F30F0000 jmp [rel clo_code+0x1000]
0F1F00 nop3
# one page away...
struct clo_slot {
void (*func)(void* _R10,...);
void* data;
};
Edit: to use r10 rather than rotating all the argument registers.
https://nullprogram.com/blog/2019/11/15/