In the pure C ++ standard (or C; see n1570 or n3337 or some newer standard specification, a document written in English), the set of functions is fixed - cannot change either - and is set by combining all your translation units ( and those from the standard C or C ++ library). And in pure standard C ++ or C, a function pointer is only allowed to point to some pre-existing function (otherwise this is undefined behavior ) when you use it for indirect calls. All functions in standard C ++ (or C), known at compile time, are practically declared in some translation unit (and are often implemented in another or in some external library).
BTW, when coding the interpreter (for some scripting languages) you do not need to increase the set of your functions (C or C ++). You just need to have (general) interpretation functions encoded in C or C ++ regarding some representation of the interpreted script code (which from the point of view of your C ++ or C program is some data), possibly AST or bytecode . For example, a Unix or Lua or Guile shell, do not create C or C ++ functions. You can include Lua or Guile in your program.
However, you may be interested in creating or creating new (C or C ++) functions at run time, for example, when compiling script code in C (a common practice ) or in machine code. This is not possible in pure standard C or C ++, but it is practically possible in many implementations using the operating system (at least to grow or add code segments , that is, a new computer , in the virtual address space ).
(note that any mechanism that can create functions at runtime goes beyond the standard C or C ++ and returns pointers to new machine code)
See also this answer (to a very close question, for C, but you can adapt it for C ++), describing in detail how this is practically possible (especially on Linux).
BTW, libffi itself is not a way to create new (C, C ++ or machine code) functions, but a call to existing functions of an arbitrary signature with arbitrary arguments.
This means that I need a way to generate argument lists of C functions at runtime.
libffi does just that. He knows your ABI (and partially encoded in assembler).
Please note that if your set of functions is fixed (so finite), their signatures are also in a finite set, then you really do not need libffi (because you can use all your signatures in a special case, so your signatures are not arbitrary), even if it may be convenient.
As soon as you add new functions during the execution of arbitrary signatures, libffi or an equivalent mechanism is absolutely necessary (because even a set of called signatures can grow).