Can C functions be changed?

See if anyone knows if it's possible to replace C ... functions?

void swap2(int(*a)(int), int(*b)(int)) { int(*temp)(int) = a; *a = *b; *b = temp; // Gives 'Non-object type 'int (int)' is not assignable } swap2(&funcA, &funcB); 

EDIT

More details here about intentions. Below are some answers that work, such as creating a ptr function using typedef , pointing them to functions, and switching them, which allows you to successfully launch new modified ptrs.

BUT call functions by their original names after replacement, there are no changes. In essence, I am looking for the c-equivalent of objc "swizzle".

I'm starting to think that this is impossible, due to the complete lack of reflection, and will require actually modifying the binary itself (obviously, this is impossible). D:

Comments are welcome.

+4
source share
5 answers

If you use function pointers as below, yes

 typedef int (*func_pt)(int); func_pt a, b; void swap(func_pt * a, func_pt * b) { func_pt tmp = *b; *b = *a; *a = tmp; } swap(&a, &b); 

Or you use it like this, I think it is not:

 int test1(int a) { return a; } int test2(int b) { return b; } swap(&test1, &test2); 

Full compilation of the work program

 #include <stdio.h> #include <stdlib.h> typedef int (* func_pt)(int); func_pt a, b; int test1(int a) { printf("test1\n"); return 1; } int test2(int a) { printf("test2\n"); return 2; } void swap(func_pt * a, func_pt * b) { func_pt tmp = *b; *b = *a; *a = tmp; } int main(void) { a = &test1; b = &test2; printf("before\n"); a(1); b(1); swap(&a, &b); printf("after\n"); a(1); b(2); return 0; } 

Output:

 before test1 test2 after test2 test1 

Some people have not tried it themselves, just say that this is absurd. Therefore, I give you an example.

+9
source

I'm sure you need pointers to function pointers to swap pointers, no? This type of swap function changes values; you really want to deal with addresses. An example of a function call will not really work, because C does not treat functions as first-class variables, so you cannot actually change functions directly; you need to use pointers for function addresses, since addresses can be replaced:

 void swap2(int(**a)(int), int(**b)(int)) { int(*temp)(int) = *a; *a = *b; *b = *temp; } int(*func1)(int) = &foo; int(*func2)(int) = &bar; swap2(&func1, &func2); 
+3
source

Your code will give an error, for example, "invalid lvalue" during assignment. As I can see in your code, you are trying to swap pointers without changing its value, so take a look at the solution below.

 void swap2(int(**a)(int), int(**b)(int)) { int(*temp)(int) = *a; *a = *b; *b = temp; } int main(){ int(*temp1)(int) = &funcA; int(*temp2)(int) = &funcB; swap2(&temp1,&temp2); } 
+1
source

Yes, you can. Think that a function pointer is just a memory address, the only requirement is: where will you keep such an address necessary for changing. Say int (*foo)() not what foo points to. May be printf() or fopen() .

+1
source

Although the subject asks for replacement features, you really want to emulate what swizzle does. This means that you want to be able to call the same function name, but to have something else.

A pointer-only solution will not give you this behavior. If this is not important to you, then you should accept one of the available function pointers. If this is important to you, then you will need to introduce an abstraction layer. An abstraction can use function pointers under the hood (although there are other solutions).

The API for users of this interface will be:

 /* API to initialize */ void abstract_func_init (); /* API to manipulate abstract functions */ typedef int abstract_func_type (); abstract_func_type * abstract_func_get (abstract_func_type *key); int abstract_func_set (abstract_func_type *key, abstract_func_type *behavior); /* the abstract functions */ extern int foo (); extern int bar (); 

An implementation of such an interface might look like this:

 static void insert (abstract_func_type *key, abstract_func_type **behavior) { /* associate key to behavior */ } static abstract_func_type ** lookup (abstract_func_type *key) { /* return behavior from key */ } abstract_func_type * abstract_func_get (abstract_func_type *k) { abstract_func_type **f = lookup(k); if (f) return *f; return 0; } int abstract_func_set (abstract_func_type *k, abstract_func_type *p) { abstract_func_type **f = lookup(k); if (f) { *f = p; return 0; } return -ENOENT; } #define DEFINE_ABSTRACT_FUNC(func) \ static int static_##func (); \ static abstract_func_type *func##_ptr = static_##func; \ int func () { return func##_ptr(); } \ static int static_##func () DEFINE_ABSTRACT_FUNC(foo) { return puts("foo"); } DEFINE_ABSTRACT_FUNC(bar) { return puts("bar"); } void abstract_func_init () { insert(foo, &foo_ptr); insert(bar, &bar_ptr); } 

Then the swap() that you originally presented in your post can be implemented as follows:

 void swap (abstract_func_type *a, abstract_func_type *b) { abstract_func_type *ap = abstract_func_get(a); abstract_func_type *bp = abstract_func_get(b); abstract_func_set(a, bp); abstract_func_set(b, ap); } 

Here is the program that calls swap() :

  puts("before swap"); foo(); bar(); swap(foo, bar); puts("after swap"); foo(); bar(); 

And his conclusion will be:

 before swap foo bar after swap bar foo 

To automate the addition of abstract functions to the lookup table, you can enter an additional step in the build system called a script, which grep prints the lines DEFINE_ABSTRACT_FUNC and generates a new source file that had a function with insert() calls for each such line.

The full version of the layout can be found here .

0
source

Source: https://habr.com/ru/post/1481097/


All Articles