C/C++ casting issue?

Member
Posts: 117
Joined: 2010.09
Post: #1
Hi all,

My knowledge of 'C' is fine; but C++ under Xcode not so hot!
I simply cannot get this to compile; the error being:

error: cannot convert 'HIT_LIST*' to 'void (**)(OBJECT_DEF*, OBJECT_DEF*)' in initialization

Relevant code:
Code:
void no_hit(OBJECT_DEF *obj1,OBJECT_DEF *obj2)
{
}


HIT_LIST hit_BLAST=
{
    &no_hit,                        // 0
};


SPAWN_DEF def_type_blast=
{
    &hit_BLAST, <--------problem here
};
header files:
Code:
typedef struct SPAWN_DEF
{
    void (**hit_list_ptab)(OBJECT_DEF *,OBJECT_DEF *);
};

typedef struct HIT_LIST
{
    void (*hit_func)(OBJECT_DEF *,OBJECT_DEF *);
};
All I am trying to do is setup HIT_LIST as an array of pointers to functions expecting (OBJECT_DEF *,OBJECT_DEF *) as input.
But the initialization of it SPAWN_DEF fails with the error.

Anyone care to help?; I assume it's a feature of xcode implementation or C++ causing casting issues that I am struggling to overcome.

Cheers
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
I think &(hit_BLAST.hit_func) will compile... that's nothing to do with Xcode, or even GCC/Clang, the code is just plain not valid as it stands.

The code is horrible, too. Double-pointer-to-function? WTH?
Quote this message in a reply
Member
Posts: 117
Joined: 2010.09
Post: #3
:-)
Well it compiles!; not sure if it works correctly yet as other things to add.
Why does my method seem horrible?

Can you suggest a nicer way (in straight C) to have a pointer to a table of function pointers?

Cheers though!!

P.S It is strange though. As I wrote this code many years ago for ps1 and it obviously compiled then. Looking at it now though I guess it shouldn't of!!! , weird.....

P.S.S Actually!, although it compiles it still gives warnings on those lines!
Just rebooted mac... errors gone!!!!!! :-/
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #4
(Nov 22, 2010 10:59 AM)markhula Wrote:  Can you suggest a nicer way (in straight C) to have a pointer to a table of function pointers?

Not sure exactly what you're looking for, but I whipped up a small function pointer example for you in C:
Code:
#include <stdio.h>
#include <stdlib.h>

typedef void (*SpawnFunc)(int myParam1);
typedef void (*HitFunc)(void *obj1, void *obj2);

typedef struct
{
    SpawnFunc    spawn;
    HitFunc        hit;
} MyFuncTable;

void testSpawnFunc(int myParam1)
{
    printf("testSpawnFunc result: %d\n", myParam1);
}

void testHitFunc(void *obj1, void *obj2)
{
    printf("testHitFunc was called.\n");
}

int main (int argc, const char * argv[]) {
    
    MyFuncTable *funcTable = malloc(sizeof(MyFuncTable));
    
    // fill them in
    funcTable->spawn = testSpawnFunc;
    funcTable->hit = testHitFunc;
    
    // test them out!
    funcTable->spawn(123);
    funcTable->hit(NULL, NULL);
    
    return 0;
}
Quote this message in a reply
Member
Posts: 117
Joined: 2010.09
Post: #5
Hi there,

Hmmm, yes.
But in my original example suppose you wanted to add another function to HIT_LIST???
i.e. you can't reference hit_func in the SPAWN_DEF...


Cheers
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #6
I am still not quite able to envision what you're looking for. Perhaps something like this you mean?

Code:
#include <stdio.h>
#include <stdlib.h>

enum
{
    MY_ASTEROID_HIT_FUNC,
    MY_ALIEN_HIT_FUNC,
    NUM_HIT_FUNCS
};

typedef void (*SpawnFunc)(int myParam1);
typedef void (*HitFunc)(void *obj1, void *obj2);

typedef struct
{
    SpawnFunc    spawn;
    HitFunc        hit[NUM_HIT_FUNCS];
} MyFuncTable;

void testSpawnFunc(int myParam1)
{
    printf("testSpawnFunc result: %d\n", myParam1);
}

void testHitFuncAsteroid(void *obj1, void *obj2)
{
    printf("testHitFuncAsteroid was called.\n");
}

void testHitFuncAlien(void *obj1, void *obj2)
{
    printf("testHitFuncAlien was called.\n");
}

int main (int argc, const char * argv[])
{
    MyFuncTable *funcTable = malloc(sizeof(MyFuncTable));
    
    // fill them in
    funcTable->spawn = testSpawnFunc;
    funcTable->hit[MY_ASTEROID_HIT_FUNC] = testHitFuncAsteroid;
    funcTable->hit[MY_ALIEN_HIT_FUNC] = testHitFuncAlien;
    
    // test them out!
    funcTable->spawn(123);
    funcTable->hit[MY_ASTEROID_HIT_FUNC](NULL, NULL);
    funcTable->hit[MY_ALIEN_HIT_FUNC](NULL, NULL);
    
    return 0;
}
Quote this message in a reply
Member
Posts: 117
Joined: 2010.09
Post: #7
Hi again,

Yes, this is what I effectively do.
The problem is assigning the HIT_LIST address (which is in itself a list of function pointers) into the SPAWN_DEF and then being able to access that and index into the HIT_LIST.
Sorry; not a good explanation! :-))

I guess I am asking; how do I get the address of hit_BLAST into my SPAWN_DEF at initialization suiting the definition in SPAWN_DEF below?

void (**hit_list_ptab)(OBJECT_DEF *,OBJECT_DEF *);


Cheers
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #8
(Nov 22, 2010 12:18 PM)markhula Wrote:  Sorry; not a good explanation! :-))

LOL, that's okay, this stuff is hard to communicate at times.

You mean accessing the list of hit function pointers from inside a call to the spawn function, perhaps like this? (mostly same as before, but calling the hit test functions from spawn instead of main, which requires a small cast (which is fine anyway, since it's slightly faster to have a local of the pointer)) <-- BTW, there's more than one way to skin this cat. This is just the way I'd probably do it.

Code:
#include <stdio.h>
#include <stdlib.h>

enum
{
    MY_ASTEROID_HIT_FUNC,
    MY_ALIEN_HIT_FUNC,
    NUM_HIT_FUNCS
};

typedef void (*SpawnFunc)(int myParam1, void *funcTable);
typedef void (*HitFunc)(void *obj1, void *obj2);

typedef struct
{
    SpawnFunc    spawn;
    HitFunc        hit[NUM_HIT_FUNCS];
} MyFuncTable;

void testSpawnFunc(int myParam1, void *funcTable)
{
    printf("testSpawnFunc result: %d\n", myParam1);
    
    MyFuncTable *func = (MyFuncTable *)funcTable;
    func->hit[MY_ASTEROID_HIT_FUNC](NULL, NULL);
    func->hit[MY_ALIEN_HIT_FUNC](NULL, NULL);
}

void testHitFuncAsteroid(void *obj1, void *obj2)
{
    printf("testHitFuncAsteroid was called.\n");
}

void testHitFuncAlien(void *obj1, void *obj2)
{
    printf("testHitFuncAlien was called.\n");
}

int main (int argc, const char * argv[])
{
    MyFuncTable *funcTable = malloc(sizeof(MyFuncTable));
    
    // fill them in
    funcTable->spawn = testSpawnFunc;
    funcTable->hit[MY_ASTEROID_HIT_FUNC] = testHitFuncAsteroid;
    funcTable->hit[MY_ALIEN_HIT_FUNC] = testHitFuncAlien;
    
    // test them out!
    funcTable->spawn(123, funcTable);
    
    return 0;
}


If you wanted to only pass the array of hit functions to spawn, you could do it similarly:

Code:
#include <stdio.h>
#include <stdlib.h>

enum
{
    MY_ASTEROID_HIT_FUNC,
    MY_ALIEN_HIT_FUNC,
    NUM_HIT_FUNCS
};

typedef void (*SpawnFunc)(int myParam1, void *hitFuncs);
typedef void (*HitFunc)(void *obj1, void *obj2);

typedef struct
{
    SpawnFunc    spawn;
    HitFunc        hit[NUM_HIT_FUNCS];
} MyFuncTable;

void testSpawnFunc(int myParam1, void *hitFuncs)
{
    printf("testSpawnFunc result: %d\n", myParam1);
    
    HitFunc *hitFunc = (HitFunc *)hitFuncs;
    hitFunc[MY_ASTEROID_HIT_FUNC](NULL, NULL);
    hitFunc[MY_ALIEN_HIT_FUNC](NULL, NULL);
}

void testHitFuncAsteroid(void *obj1, void *obj2)
{
    printf("testHitFuncAsteroid was called.\n");
}

void testHitFuncAlien(void *obj1, void *obj2)
{
    printf("testHitFuncAlien was called.\n");
}

int main (int argc, const char * argv[])
{
    MyFuncTable *funcTable = malloc(sizeof(MyFuncTable));
    
    // fill them in
    funcTable->spawn = testSpawnFunc;
    funcTable->hit[MY_ASTEROID_HIT_FUNC] = testHitFuncAsteroid;
    funcTable->hit[MY_ALIEN_HIT_FUNC] = testHitFuncAlien;
    
    // test them out!
    funcTable->spawn(123, funcTable->hit);
    
    return 0;
}
Quote this message in a reply
Member
Posts: 117
Joined: 2010.09
Post: #9
:-)

My problem is at initialisation though.
I don't want to assign my HIT_LIST to my SPAWN_DEF at runtime.
I simply can't work out how/what I cast the hit_blast too within the SPAWN_DEF.
If that makes any sense!! :-))))

Cheers

P.S
(void **)&hit_BLAST, in the spawn_def seems correct but the compiler moans with error: invalid conversion from 'void**' to 'void (**)(OBJECT_DEF*, OBJECT_DEF*)'
It looks like the parameter definition (OBJECT_DEF *,OBJECT_DEF *) is a problem.
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #10
Hmm... Well, in C, you can only assign pointers (which includes function pointers) at runtime. Is there a particular reason you cannot/want-not do it during runtime?

[edit] Hang on a second. I just saw your edit above. I'll take another stab at an example in a bit.
Quote this message in a reply
Member
Posts: 117
Joined: 2010.09
Post: #11
I can't see why the function pointer cannot be assigned at init.
Currently the stuff I am porting does seem to have this in; and whilst I could probably hack in a fix it would be a real pain.
You can assign function pointers at compile time (i.e. init them from their address into a structure); it's just this particular case the compiler chokes on and I can't see why.
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #12
(Nov 22, 2010 12:47 PM)markhula Wrote:  You can assign function pointers at compile time

Not in C.

Do you still want a straight C example, or are you sticking with C++?
Quote this message in a reply
Member
Posts: 117
Joined: 2010.09
Post: #13
You mis-understand me (I thought you might :-)))))) )

If I have a func:

void func(DEF *o1,DEF *o2)

You can assign the address of func into a void * function pointer such as &func.
That's what I meant :-)

I am simply trying to do the same; it should work.
To recap (as I feel were going off on a tangent perhaps)


HIT_LIST hit_BLAST[]=
{
&no_hit, // 0
};


SPAWN_DEF def_type_blast=
{
&hit_BLAST, <-- here I want the address of hit_blast function array
};

SPAWN_DEF line for that definition is:
void (**hit_list_ptab)(OBJECT_DEF *,OBJECT_DEF *);
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #14
Hmm... I know this is incredibly unhelpful, but it isn't obvious to me why what you're trying to do won't work either. Rasp

Long shot: does adding parentheses help? &(hit_BLAST)

You said earlier:

Quote:Just rebooted mac... errors gone!!!!!! :-/

That shouldn't happen. ... and you should never have to reboot your Mac during development. Did you try cleaning your project? (Build->Clean All Targets) We are talking about Xcode though, so weird things do happen from time to time.
Quote this message in a reply
Member
Posts: 117
Joined: 2010.09
Post: #15
Hurray!
Got it working at last.

Just for the record and also I did appreciate your help.
I made my HIT_LIST a macro and got exactly what I wanted thus:

#define HIT_LIST(name) void( *name[MAX_NUM_TYPES])(OBJECT_DEF *ob1,OBJECT_DEF *ob2)=

allowing me to:

HIT_LIST(hit_BLAST)
{
&no_hit, // 0
&wall_hit,
};

Hopefully you can see what I was trying to do! :-))))))))))

Cheers & thanks again. Not posted that often but it's great to know people are out there trying to help.
Quote this message in a reply
Post Reply