rust-guide icon indicating copy to clipboard operation
rust-guide copied to clipboard

C++ functor or function pointer?

Open Voronar opened this issue 2 years ago • 3 comments

"When binding with C or even C++, one cannot guarantee easily the validity of the function pointer. C++ functors are not C-compatible". https://github.com/ANSSI-FR/rust-guide/blob/master/src/en/07_ffi.md?plain=1#L455

Voronar avatar Jan 26 '22 12:01 Voronar

I think it's a "moreover, functors are not C++ compatible" kind of sentence, as in adding extra info rather than deducing info from the previous sentence. I'd personally thus rephrase it as such, with even an added "e.g., lambdas" attached to the "functors" mention:

When binding with C or even C++, one cannot [easily] guarantee [] the validity of the function pointer. [Moreover,] C++ functors [(e.g., lambdas or std::functions)] are not [directly] C-compatible.

  • The directly is added since any functor can be made C-compatible by virtue of a helper "thunk" / trampoline function —so as to split it into the usual data pointer + function pointer: Demo (main interesting thing is the synthesize_ftor_virtual_call_method).

danielhenrymantilla avatar Jan 26 '22 13:01 danielhenrymantilla

Thanks for the explanation. My first confusion was that functor is a shortcut for "function pointer". 🙃

Voronar avatar Jan 26 '22 13:01 Voronar

Yeah, the terms in this area are both quite overloaded for some, and quite diverse for others. A C++ functor seems to be what other languages call a callable, i.e., anything with an operator() method. In Rust parlance, it would be an impl Fn….

  • (FWIW, other languages (mainly functional ones) call functor any higher-level function; and in the case of OCaml, a Functor is kind of like a generic(-over-another trait implementor) trait (implementation or definition))

Then we have dynamic callables, which are type-erased and thus can be unified under the same type / umbrella (e.g., Box<dyn Fn…> in Rust), which in C++ would be std::function.

Moreover, we have a way to express, within a single expression, the definition of an anonymous callable / impl Fn… / functor, which is allowed to capture, implicitly or explicitly, local variables from its surrounding environment, called closure( expression)s in Rust, and lambda( expression)s in C++.

We also have functions, as in free functions (or methods), which thus are not allowed to refer to captured state: all its state is given through its arguments (although in the case of C++, methods have the implicit this parameter), or global state (albeit not recommended).

And finally, we have function pointers, which would be the dynamic / type-unified version of (thus capture-less) functions.

danielhenrymantilla avatar Jan 26 '22 14:01 danielhenrymantilla