How to dynamically generate an `extern "C" fn` function

I know Rust can dynamicly generates closure function, such as FnOnce, FnMut, Fn.

Currently I want to dynamically generate an extern "C" function,
provide this as a function pointer to a foreigh C function.
Is this possible?

For example, is it possible to generate

extern "C" fn foo() -> i32 {
   return XXXX; // Return value is specified on function generation
}

This sounds quite different Rust from the one I know. Care to explain what do you mean by that?

Depends on answer to the previous question, I suspect.

When you create a closure the function is always the same and known at compile time, what changes instead is a hidden argument of that function carrying the context. This data is also part of the closure (it's the data it closes over, hence the name) which is why you can't always convert them to a fn() pointer (because that's missing the argument for the context and the context itself!). For a similar reason you cannot dynamically generate an extern "C" function item/function pointer in the same way that closures work.

Note that technically you can still generate such functions, but it's pretty hard because it will involve either dynamic code generation (not portable, not always possible) or whatever fuckery GCC uses for implementing nested functions.

2 Likes

C libraries which take function pointers also often take some arbitrary pointer which they'll hold onto and pass back when calling your function — this might be called “user data”, “refcon”, or various other names. You can use this to effectively make your own closure — put the data you need in a Box and call Box::into_raw() on it, then pass that pointer.

3 Likes

If you mean trampolines then it's all explained pretty well in the GCC documentation. It's also a code generation, just function is generated right there, on stack.

GCC's nested functions are also incompatible with any platform that doesn't allow mapping the stack as executable like for example arm64 macOS, iOS, game consoles, SELinux (depending on it's configuration), OpenBSD and NetBSD.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.