views:

298

answers:

2

I am porting some C code to a TI DSP chip environment. I'm grappling with the C compiler.

I have a data structure that includes a pointer to a function. I have a function that initializes the data structure. Something like this:

typedef void (*PFN_FOO)(int x, int y);

struct my_struct
{
    PFN_FOO pfn;
};

init_struct(struct my_struct *p, void *pfn)
{
    p->pfn = (PFN_FOO)pfn;
}

Under Visual Studio and GCC this sort of code compiles without complaint. In fact, because the pfn argument is type void * I don't really need to even put a cast there; it would just implicitly cast without complaint.

In Code Composer Studio for the TI DSP chips, I get "warning: invalid type conversion"

My policy is to make my code compile without warnings, so I want to fix this. I have tried all sorts of casting. I discovered that the compiler is perfectly happy if I cast my void * pointer to int first, and then cast it to the correct type. Ew, yuck!

How can I do this cast without the compiler complaining? Do I really have to cast to int to shut up the compiler?

Note: I am specifically not looking for a solution to the effect of "change init_struct() to accept a PFN_FOO instead of a void *". That would work for this simplified code snippet, but would not work for the actual code, which builds a list of possibly heterogeneous stuff.

+3  A: 

Shouldn't you write?

typedef void (*PFN_FOO)(int x, int y);

See this tutorial.

dirkgently
Er, yes. I have it correct in the actual code, and I'll change my stupid example code to be correct. Now, do you have any advice on the actual question?
steveha
Just to clarify: you might have suspected that the problem was my code not declaring the PFN_FOO type correctly. That is not the problem, and the code actually works quite well, but the TI DSP C compiler is giving me warnings on it.
steveha
Are you compiling as C or C++?
dirkgently
The project is C code.
steveha
If this were C++, I wouldn't have to mess around with this stuff; I could use virtual pointers and C++ would do all the work for me.
steveha
+3  A: 

Standard C specifically does not support conversions between pointers to data objects and pointers to functions. GCC and Visual Studio support this as an extension.

If you want to make your function standard-conforming, you will need to wrap the pointer-to-function inside a struct and pass it via that:

struct pfn_foo_holder {
    PFN_FOO fp;
};

init_struct(struct my_struct *p, void *pfn)
{
    struct pfn_foo_holder *foo_holder = pfn;
    p->pfn = foo_holder->fp;
}

The caller must then also wrap the function pointer up in such a struct when it makes the call:

struct pfn_foo_holder holder = { &somefunc };
/* ... */
init_struct(p, &holder);
caf
Wow, I was thinking this was a TI C thing, but you are telling me it is a C standard thing. That's very helpful.
steveha
Okay, I rewrote my function so that instead of taking a `void *`, it takes a `PFN`, defined as so: `typedef void (*PFN)();` And now the code compiles without warning. It's enough that it starts out as some kind of pointer to function, before being cast into a specific PFN type. Thank you! Answer accepted and +1.
steveha
That's right, you can freely convert between different function pointer types.
caf