Fake anonymous functions in C
Asked Answered
N

3

13

In this SO thread, Brian Postow suggested a solution involving fake anonymous functions:

make a comp(L) function that returns the version of comp for arrays of length L... that way L becomes a parameter, not a global

How do I implement such a function?

Ninetieth answered 30/10, 2009 at 15:9 Comment(9)
I don't think it's necessary to provide a link to the top page of stackoverflow.com in your question.Dorsiventral
The question you link to is about how to do it in C++. This question is tagged C. Which do you want to know about?Jay
The solution Barry provided is in C. Most of the comments suggested that it's not possible to solve my first question in C++.Ninetieth
I am really interested to see if someone can come up with a good way to do this in standards compliant C.Fukien
Well, since Brian was also talking about copying the array into a vector and back again (suggesting it would take 2ns, or about 3 clock cycles to copy each way), I'm not convinced he's serious and knows what he's talking about. I'm not aware of any way to implement closures in C. You can "cheat" by relying on global or thread-local data, but calling conventions and the nature of a function pointer make it impossible for two different calls to the same function to "see" different values of L unless either (a) it has changed, or (b) the calls are made in different contexts.Jay
... and there's certainly no way in standard C to create functions at runtime by generating new code. Btw this is exactly why the standard C qsort function should have had an additional "user data pointer" parameter, which is passed on to the comparator.Jay
@Alexandru: Who's Barry and where can I take a look at the solution he provided?Martini
@AndreyT: Brian. It was a typo. I provided a link to his comment.Ninetieth
@Alexandru: I followed the "Brian" link, but I didn't find any solution there. Just a rather vague suggestion based on a big "if". And he doesn't say anything about C in his reply.Martini
M
6

See the answer I just posted to that question. You can use the callback(3) library to generate new functions at runtime. It's not standards compliant, since it involves lots of ugly platform-specific hacks, but it does work on a large number of systems.

The library takes care of allocating memory, making sure that memory is executable, and flushing the instruction cache if necessary, in order to ensure that code which is dynamically generated (i.e. the closure) is executable. It essentially generates stubs of code that might look like this on x86:

  pop %ecx
  push $THUNK
  push %ecx
  jmp $function
THUNK:
  .long $parameter

And then returns the address of the first instruction. What this stub does is stores the the return address into ECX (a scratch register in the x86 calling convention), pushes an extra parameter onto the stack (a pointer to a thunk), and then re-pushes the return address. Then, it jumps to the actual function. This results in the function getting fooled into thinking it has an extra parameter, which is the hidden context of the closure.

It's actually more complicated than that (the actual function called at the end of the stub is __vacall_r, not the function itself, and __vacall_r() handles more implementation details), but that's the basic principle.

Metsky answered 31/10, 2009 at 15:51 Comment(0)
A
2

I don't believe you can do that with C99 -- there's no partial application or closure facility available unless you start manually generating machine code at runtime.

Apple's recently proposed blocks would work, though you need compiler support for that. Here's a brief overview of blocks. I have no idea when/if any vendor outside apple will support them.

Agnew answered 31/10, 2009 at 13:59 Comment(1)
The clang compiler supports Blocks, apparently because Apple funds the project.Disrobe
M
1

It is not possible to generate ordinary functions during run-time in either C or C++. What Brian suggested is based on a big "if": "...if you can fake anonymous functions...". And the answer to that "if" is: no, you can't. (Although it is not clear what he meant by "fake".)

(In C++ it is possible to generate function-like objects at run time, but not ordinary functions.)

The above applies to standard C and C++ languages. Particular implementations can support various implementation-provided extensions and/or manually-implemented hacks, like "closures", "delegates" and similar stuff. Nothing of that, of course, have anything to do with standard C/C++ languages.

Martini answered 30/10, 2009 at 17:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.