1

I have a function which expects parameters like this

void priqueue_init(priqueue_t *q, int(*comparer)(void *, void *))

I want it to be able to take arguments of any type.

In a separate file I first typedef

typedef int (*comp_funct)(job_t*, job_t*);

And the function I want to pass...

int fcfs_funct1(job_t* a, job_t* b)
{
  int temp1 = a->arrival_time;
  int temp2 = b->arrival_time;

  return (temp1 - temp2);
}

The call to priqueue_init:

priqueue_init(pri_q, choose_comparator(sched_scheme));

And finally, my choose_comparator function:

comp_funct choose_comparator(scheme_t scheme)
{
    if (sched_scheme == FCFS)
        return fcfs_funct1;

    return NULL;
}

I error on my call to priqueue_init.

    libscheduler/libscheduler.c: In function ‘add_to_priq’:
libscheduler/libscheduler.c:125:3: error: passing argument 2 of ‘priqueue_init’ from incompatible pointer type [-Werror]
In file included from libscheduler/libscheduler.c:5:0:
libscheduler/../libpriqueue/libpriqueue.h:25:8: note: expected ‘int (*)(void *, void *)’ but argument is of type ‘comp_funct’

Where am I getting hung up? The file where priqueue_init is defined doesn't know about the type job_t. I thought going with void arguments was the way to go.

Collin
  • 1,777
  • 4
  • 26
  • 42

2 Answers2

3

int (*comparer)(void *, void *) and int (*comp_funct)(job_t*, job_t*) aren't compatible types. Change them to match, or add a typecast.

Pointers (void * and job_t * in your case) don't have to be the same size, so the compiler is rightly giving you an error. Since they are the same size on most machines, a simple typecast might solve your problem, but you'd be introducing some potential nonportability.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • I didn't actually know this, but it's verified in this answer to [Are all data pointers of the same size in one platform?](http://stackoverflow.com/a/1241314/188535). How can `memcpy` and friends possibly be guaranteed to work then? – detly Oct 23 '13 at 22:54
  • 1
    @detly, conversions to and from `void *` are well defined. The calling conventions needn't make them compatible, though, which is why the function pointer in OP's question has a problem. – Carl Norum Oct 24 '13 at 03:28
2

To be compatible with the function type signature, your comparison functions must take void* parameters, and cast them internally:

int fcfs_funct1(void* a, void* b)
{
  int temp1 = ((job_t*)a)->arrival_time;
  int temp2 = ((job_t*)b)->arrival_time;

  return (temp1 - temp2);
}
Carl Norum
  • 219,201
  • 40
  • 422
  • 469
Barmar
  • 741,623
  • 53
  • 500
  • 612