Passing function pointers as arrays of chars

O

Olaf Dietrich

I may just be temporarily (hopefully ...) stupid, but how can
I pass a function pointer between functions using an array of
(signed/unsigned) chars (in a standard-conforming way)?


E.g.:

I have a function: int (*func)(double, int).

Now I'd like to store the "address" of this function
in an array (of sufficient size) of chars, e.g. in
char func_addr[100]. (How can I do this?)

And finally I would like to use this address in another
function pointer:
new_func = (int (*)(double, int)) func_addr.

This doesn't work - gcc complains: "ISO C forbids conversion
of object pointer to function pointer type".


Is there a way to store the data that constitutes the function
pointer in an array of chars (that need not have the size of
an object pointer)? And then to re-interpret this sequence of
bytes again as a function pointer?


Thanks for any suggestions
Olaf
 
J

James Kuyper

Olaf said:
I may just be temporarily (hopefully ...) stupid, but how can
I pass a function pointer between functions using an array of
(signed/unsigned) chars (in a standard-conforming way)?


E.g.:

I have a function: int (*func)(double, int).

Now I'd like to store the "address" of this function
in an array (of sufficient size) of chars, e.g. in
char func_addr[100]. (How can I do this?)


char func_addr[sizeof func];
memcpy(func_addr, &func, sizeof func);
And finally I would like to use this address in another
function pointer:
new_func = (int (*)(double, int)) func_addr.

memcpy(&new_func, func_addr, sizeof new_func);
This doesn't work - gcc complains: "ISO C forbids conversion
of object pointer to function pointer type".

That's because you're trying to convert func_addr, which in this context
decays into a pointer to the first char of that array, into a pointer to
a function. What you want it to do is interpret the contents of that
array as if it were a pointer to a function. The syntax for such a
conversion (were it safe) would be:

new_func = *(int (**)(double, int)) func_addr;

This converts func_addr from a pointer to an array of char into a
pointer to a function pointer, then dereferences that pointer, obtaining
a function pointer. This is not, unfortunately, a safe approach to
use, because there's no guarantee that func_addr is correctly aligned to
hold such a pointer. You could guarantee correct alignment if func_addr
were a pointer to a dynamically allocated array of char, or if func_addr
were part of a union with a the appropriate function pointer type.
 
O

Olaf Dietrich

James Kuyper said:
Olaf said:
Now I'd like to store the "address" of this function
in an array (of sufficient size) of chars, e.g. in
char func_addr[100]. (How can I do this?)

char func_addr[sizeof func];
memcpy(func_addr, &func, sizeof func);
And finally I would like to use this address in another
function pointer:

memcpy(&new_func, func_addr, sizeof new_func);

How obvious and simple ... (and it even works).

Thank you very much for your help
Olaf
 
N

Nick Keighley

I may just be temporarily (hopefully ...) stupid, but how can
I pass a function pointer between functions using an array of
(signed/unsigned) chars (in a standard-conforming way)?

why do you want to do this? Some sort of callback function?
It's best avoided if you can.

<snip>
 
V

vippstar

Olaf said:
I may just be temporarily (hopefully ...) stupid, but how can
I pass a function pointer between functions using an array of
(signed/unsigned) chars (in a standard-conforming way)?

I have a function: int (*func)(double, int).
Now I'd like to store the "address" of this function
in an array (of sufficient size) of chars, e.g. in
char func_addr[100]. (How can I do this?)

char func_addr[sizeof func];
memcpy(func_addr, &func, sizeof func);

How will this work since the conversion between void * and a function
pointer needs not to be meaningful? (6.3.2.3)
(notice the memcpy call)
Also, while the first line is possible for function pointers, it's not
for function designators;
This is correct:

void (*fp)(void);
char foo[sizeof fp];

This is incorrect:

char foo[sizeof strcpy];

Because it violates the constraint in 6.5.3.4
 
J

jameskuyper

Olaf Dietrich wrote: ....
I have a function: int (*func)(double, int).
Now I'd like to store the "address" of this function
in an array (of sufficient size) of chars, e.g. in
char func_addr[100]. (How can I do this?)

char func_addr[sizeof func];
memcpy(func_addr, &func, sizeof func);

How will this work since the conversion between void * and a function
pointer needs not to be meaningful? (6.3.2.3)
(notice the memcpy call)

No such conversion is performed by this code. The only pointers being
converted are func_addr and &func, in the memcpy() call that you refer
to. Both of those are pointers to objects. func_addr is pointer to a
char object, and &func is a pointer to a function pointer object.
Neither one is a pointer to a function. func itself is a pointer to a
function, but func is NOT being converted to void*.
Also, while the first line is possible for function pointers, it's not
for function designators;

The question I answered was specifically about func, which is a
function pointer object. Function pointer values have to be stored in
a function pointer object before this approach can be used.
 
V

vippstar

Olaf Dietrich wrote: ...
I have a function: int (*func)(double, int).
Now I'd like to store the "address" of this function
in an array (of sufficient size) of chars, e.g. in
char func_addr[100]. (How can I do this?)
char func_addr[sizeof func];
memcpy(func_addr, &func, sizeof func);
How will this work since the conversion between void * and a function
pointer needs not to be meaningful? (6.3.2.3)
(notice the memcpy call)

No such conversion is performed by this code. The only pointers being
converted are func_addr and &func, in the memcpy() call that you refer
to. Both of those are pointers to objects. func_addr is pointer to a
char object, and &func is a pointer to a function pointer object.
Neither one is a pointer to a function. func itself is a pointer to a
function, but func is NOT being converted to void*.

Could you give me the type of func?
You say it's a pointer to a function pointer.
Does it mean it's T (**)()?
If so, then your code works and I apologise, however... (read below)
The question I answered was specifically about func, which is a
function pointer object. Function pointer values have to be stored in
a function pointer object before this approach can be used.

Here you say func is a function pointer object, which contradicts what
you said before.

After some test, I realize where I was wrong:

& doesn't have an effect with function designators, however it does
have for function pointers.
Therefore, your code is correct and I was wrong. :)
 
J

jameskuyper

....
Could you give me the type of func?

See above. It's the first line of the message you were responding to.
You say it's a pointer to a function pointer.

No, I said that &func is a pointer to a function pointer. func itself
is the function pointer that &func points at.
Does it mean it's T (**)()?

No, &func has type int (**)(double,int).

....
....
Here you say func is a function pointer object, which contradicts what
you said before.

The first statement was about &func, the second statement was about
func.
& doesn't have an effect with function designators, however it does
have for function pointers.
Therefore, your code is correct and I was wrong. :)

Well, that would explain the confusion.
 
V

vippstar

You already had it.

Yes, but afterwards I explained in my post my confusion.
I have the habbit of writing my message as I read the other article,
which I think makes my messages somewhat unclear, so I'm trying to
stop doing it.
 
O

Olaf Dietrich

Nick Keighley said:
why do you want to do this? Some sort of callback function?

I was trying to pass a pointer to a C function (used for
non-linear numerical fitting) between Tcl commands. I can
easily pass arbitrary binary data as arrays of (unsigned)
chars using the available library "procedures" such as
Tcl_SetByteArrayObj(), but it's not possible to pass
function pointers directly (without defining any additional
new types of Tcl objects etc.)

It's best avoided if you can.

It's sort of quick and dirty, but it works (using
memcpy as suggested by James Kuyper).


Olaf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,520
Members
44,996
Latest member
rainocode

Latest Threads

Top