Jump to content
  • Advertisement
Sign in to follow this  
DracoLacertae

C function pointer question from hell

This topic is 2603 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

At work, we came up with a crazy C question we couldn't figure out. Maybe the internet knows the answer. How do you specify a pair of functions that can take a pointer to each other? Huh?

Start with two functions, each can take a void *:


int f (int a, void* g_pointer );
int g(float b , void* f_pointer );





Now, we can rewrite 'g' properly, not using void *:

int g( float b, int (*f_pointer)(int a, void* g_pointer));

But now, how do you rewrite f:

int f( int a, int (*g_pointer) (float b, int (*f_pointer)(int a, void* g_pointer)));

Trying to get rid of the void* seems an endless loop. Any ideas? (No, this is not for a project, its out of curiosity. Both of us here have decided neither of us will try to write something like this, ever ! )

I know how to make two structs self reference:


typedef struct a_s
{
struct b_s* the_b;
} a_t;

typedef struct b_s
{
struct a_s* the_a;
} b_t;



Is there anything similar for functions?

Share this post


Link to post
Share on other sites
Advertisement
I don't see how this is anything more than a trivial infinite recursion. A is B is A is B... you can't escape from that spiral. I don't even think C is relevant here; you have a circular definition to begin with.

Share this post


Link to post
Share on other sites
Wait... I think I get where this is going. Pardon the rusty C syntax.


typedef int (*funcUsingInt)(int, struct Wrapper *);
typedef int (*funcUsingFloat)(float, struct Wrapper *);

struct Wrapper
{
funcUsingInt usingInt;
funcUsingFloat usingFloat;
};

// Usage
int main()
{
struct Wrapper wrapper;
wrapper.usingInt = functionUsingAnInt;

functionUsingAFloat(42.0f, &wrapper);
}



Exercise to the reader: use a discriminated union to minimize storage space :-)

Share this post


Link to post
Share on other sites
This works for me:

[source lang="cpp"]

typedef int (*fptr)(int a, const struct gwrapper &g);
typedef int (*gptr)(float b, const struct fwrapper &f);

struct gwrapper {
gptr gfn;
gwrapper(const gptr &g) : gfn(g) {}
};

struct fwrapper {
fptr ffn;
fwrapper(const fptr &f) : ffn(f) {}
};

//dummy for test
int gFunction(float a, const fwrapper &f) { return 0; }
int fFunction(int a, const gwrapper &g) { return 0; }

int main()
{
fFunction(42.0f, gFunction);
gFunction(-1, fFunction);
}
[/source]

though I agree - I can't see why you'd ever want to do this

Share this post


Link to post
Share on other sites
If you are using pure C, how about just keep the parameter as void * and force cast the function pointer to void *?
Then in the function body, cast void * back to int (*)(int, void *) and call it?
Or C forbids that kind of casting? (sorry, I was not a pure C guy).

However, your this kind of using seems quite weird. If I were you, I would rethink what's wrong with the design...

Share this post


Link to post
Share on other sites

If you are using pure C, how about just keep the parameter as void * and force cast the function pointer to void *?
Then in the function body, cast void * back to int (*)(int, void *) and call it?
Or C forbids that kind of casting? (sorry, I was not a pure C guy).


Type safety.


Share this post


Link to post
Share on other sites

This works for me:

[snip]

though I agree - I can't see why you'd ever want to do this


Cheater - that's C++ ;-)

Share this post


Link to post
Share on other sites
Yeah, I have no idea why I would want to do this either. We were defining an API wrapper that had some callbacks, so the library we were abstracting away was calling our callback, which in turn, would sometimes call to our user's callback. (A callback in a callback.) Then I said, at least the callbacks aren't calling each other, and then the whole idea of it was possible to have two functions accept each other as a parameter, without using void * came up.


But it seems void * seems the easiest way, I suppose. Its not typesafe, but whatever. Sometimes using void* with a well written comment is much clearer than some complicated device to try to get rid of it.

Share this post


Link to post
Share on other sites
You can also use my disgusting hack from above, except storing the two different function pointers in a union. Less likely to run afoul of undefined behavior circling void*, but still non-type-safe and requires tweaking the callback-invocation implementation to invoke the correct pointer based on the discriminant of the union in at least one call site.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!