Callbacks
BBC BASIC for Windows supports callbacks but BBC BASIC for SDL 2.0 doesn't. This is largely because of the number of different ABIs that would need to be supported, and the difficulty (maybe impossibility) of achieving it in C.
Is there any way, in the C programming language, of calling a function whose signature (number and types of parameters) can be specified at runtime (e.g. in a variable of some sort) rather than explicitly (i.e. known at compile time)?
Is there perhaps some way in which the varargs feature of C could be leveraged to achieve this?
Is there any way, in the C programming language, of calling a function whose signature (number and types of parameters) can be specified at runtime (e.g. in a variable of some sort) rather than explicitly (i.e. known at compile time)?
Is there perhaps some way in which the varargs feature of C could be leveraged to achieve this?
0
Comments
-
I really do not know. Varargs has always bent my brain into uncomfortable shapes, so I can't say for certain whether it would help.0
-
I really do not know. Varargs has always bent my brain into uncomfortable shapes, so I can't say for certain whether it would help.
Does the linker know that it's a varargs function and somehow arrange to call it differently, or is it just like any other exported function as far as the linker is concerned? If the linker doesn't know, it suggests that a callback could successfully be made to that function.
One feature of varargs functions is that they must be able to determine how many parameters there are, either by passing that information explicitly, or deducing it (which is how printf and scanf do it, because the number of parameters is implied by the format string).
That's not in itself a barrier to using a varargs function as a callback, because one would make the number of parameters something specified when the callback is declared in BASIC.0 -
I think the problem there is that with varargs the number of parameters is known at compile time, whereas using it as a callback in BASIC is that value is unknown at compile time.
Could this be implemented by defining a parameter block so that at the C layer all that's being passed is a memory location, then the BASIC implementation can examine that block as it will know the structure expected even if it is not known to the C layer?0 -
I think the problem there is that with varargs the number of parameters is known at compile time, whereas using it as a callback in BASIC is that value is unknown at compile time.
va_start(ap, count); /* Before C23: Requires the last fixed parameter (to get the address) */ for (j = 0; j < count; j++) { sum += va_arg(ap, int); /* Increments ap to the next argument. */ } va_end(ap);
That being the case I don't believe it does need to be known at compile time.Could this be implemented by defining a parameter block so that at the C layer all that's being passed is a memory location, then the BASIC implementation can examine that block as it will know the structure expected even if it is not known to the C layer?
0 -
Hated_moron wrote: »That being the case I don't believe it does need to be known at compile time.
a = average(2, b, c); d = average(3, e, f, g); h = average(4, i, j, k, l);
So your assertion that "with varargs the number of parameters is known at compile time" is not (always) correct.0 -
Fair enough - I stand corrected.0
-
Hated_moron wrote: »the difficulty (maybe impossibility) of achieving it in C.
The reason is easy to see: the only way of distinguishing between two or more different callbacks is by the memory address being called so an arbitrary number of callbacks means an arbitrary number of addresses, and you can't do that in compiled C. You must generate the code of the callback, or at least its entry point, at run time.
One small caveat, you could in principle check the return address and attempt to determine which callback it is from that. But there's no guarantee that the same callback function won't be called from two or more places, nor that multiple callback functions aren't called from the same place (e.g. via a dispatch mechanism).
So it simply isn't possible to implement (an arbitrary number of) callbacks in versions of BBCSDL in which the assembler is unusable (e.g. iOS and 'Apple Silicon' MacOS). On other versions a callback library would be possible, using the same approach as the BB4W library.
0