Rev | Author | # | Line |
---|---|---|---|
12 | AristotlePagaltzis | 1 | [C] is probably the only language you can do this in (except maybe [Forth]). Other languages either have no way of doing this, or don't treat data and code differently. |
10 | JohnMcPherson | 2 | (Feel free to add examples for other languages here.) |
3 | |||
4 | Once you've got a pointer to your machine code (usually an array of bytes or ints), you need to cast it to the appropriate type and call it. Eg if you have a pointer to a function which takes a char *, you can call it like this: | ||
5 | |||
6 | ((int (*)(char *)) p)("hello, world"); | ||
7 | |||
8 | The secret here is the parenthesis around the star. To declare a variable to hold the above, use this: | ||
9 | |||
10 | int (*func_t)(char *); | ||
11 | |||
11 | JohnMcPherson | 12 | In C (and [C++]), a function name is really just a pointer to a function, and you can think of () as an operator to make a call to that function. Using a typedef to hold the function type might make that clear: |
13 | |||
14 | typedef int (*func_t)(char *); | ||
10 | JohnMcPherson | 15 | |
16 | int foo(char *x) { | ||
17 | printf("%s",x); | ||
18 | } | ||
19 | |||
20 | |||
11 | JohnMcPherson | 21 | func_t p = foo; /* assign function pointer to p */ |
22 | return p("Narf!"); /* call that function, and return the result */ | ||
10 | JohnMcPherson | 23 | |
24 | ----- | ||
25 | |||
26 | And you need to do this why? | ||
27 | |||
28 | * Jon was using it to "compile" something then jump to it in C, by casting an array as a function, then calling it. | ||
29 | |||
30 | * I use it frequently to do things like have a lookup table of name to function. For example in ircu, there is a function called "parse" which takes a line from a user, splits it up into a function and it's arguments, then scans through a table of functions and their names, when it finds one that matches that command, it calls the function with the arguments it parsed earlier. Nice 'n zippy. | ||
31 | |||
32 | * A library back-end may provide functionality that should behave differently for different front ends. For example, a library that wants to print out diagnostic messages uses a function pointer, and then a console app can pass a pointer to a function that prints out to the terminal (or stdout(3) or stderr(3)) while a graphical app can create a callback function that pops up a [GUI] window or something. | ||
33 | |||
34 | * Some functions take another function as an argument. Probably the most well-known example is qsort(3) the quick sort algorithm -- you need to pass it an array and a function for comparing array elements. Also see the example below. | ||
35 | |||
36 | |||
37 | from atexit(3): | ||
38 | #include <stdlib.h> | ||
39 | int atexit(void (*function)(void)); | ||
40 | |||
41 | you can specify functions to be executed after main() finishes. | ||
42 | You do this by calling atexit(functionname), as a function name | ||
43 | without () is a pointer to that function. However, if you want to this for a function that returns something other than null, you have to type cast it. Eg: | ||
44 | (int endwin() is an ncurses function). | ||
45 | |||
46 | atexit(endwin); | ||
47 | source.cpp:227: passing `int (*)()' as argument 1 of `atexit(void (*)())' | ||
48 | atexit(void)endwin); | ||
49 | source.cpp:227: void value not ignored as it ought to be | ||
50 | |||
51 | The trick is to cast the pointer to a function pointer of the required type: | ||
52 | atexit( (void(*)())endwin ); | ||
53 | |||
54 | ---- | ||
55 | It is worth noticing that in languages where functions are first class objects (such as [LISP] and [Scheme]), passing around pointers to functions is entirely normal (and type safe); even in [Java] and [Python] [Introspection] allows type safe access to such functionality. |
lib/blame.php:177: Warning: Invalid argument supplied for foreach()