Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C (void *) used as polymorphic function pointer

I'm trying to create a system call handler, and I'm not sure how to store it.

I'm using the following typedef to store a (void *) pointer, which should receive the address of the function and an integer arg_no representing the number of arguments. Then, I create an array of this type.

typedef struct
{
  void *foo;
  int arg_no;
}td_sys_call_handler;

td_sys_call_handler ish[SYSCALL_HANDLER_NUM];

I'm trying to initialize the array in the following manner.

  ish[0].foo  = void     (*halt) (void);                  ish[0].arg_no  = 0;
  ish[1].foo  = void     (*exit) (int status) NO_RETURN;  ish[1].arg_no  = 1;
  ish[2].foo  = pid_t    (*exec) (const char *file);      ish[2].arg_no  = 1;
  ish[3].foo  = int      (*wait) (pid_t);                 ish[3].arg_no  = 1;
  ish[4].foo  = bool     (*create) (const char *file, unsigned initial_size);
                                                          ish[4].arg_no  = 2;
  ish[5].foo  = bool     (*remove) (const char *file);    ish[5].arg_no  = 1;
  ish[6].foo  = int      (*open) (const char *file);      ish[6].arg_no  = 1;
  ish[7].foo  = int      (*filesize) (int fd);            ish[7].arg_no  = 1;
  ish[8].foo  = int      (*read) (int fd, void *buffer, unsigned length);
                                                          ish[8].arg_no  = 3;
  ish[9].foo  = int      (*write) (int fd, const void *buffer, unsigned length);
                                                          ish[9].arg_no  = 3;
  ish[10].foo = void     (*seek) (int fd, unsigned position);
                                                          ish[10].arg_no = 2;
  ish[11].foo = unsigned (*tell) (int fd);                ish[11].arg_no = 1;

But all the assignments from the function pointer to the void pointer produce the following error:

../../userprog/syscall.c: In function ‘syscall_init’:
../../userprog/syscall.c:76:17: error: expected expression before ‘void’
../../userprog/syscall.c:77:17: error: expected expression before ‘void’
../../userprog/syscall.c:78:17: error: expected expression before ‘pid_t’
../../userprog/syscall.c:79:17: error: expected expression before ‘int’
../../userprog/syscall.c:80:17: error: expected expression before ‘_Bool’
../../userprog/syscall.c:82:17: error: expected expression before ‘_Bool’
../../userprog/syscall.c:83:17: error: expected expression before ‘int’
../../userprog/syscall.c:84:17: error: expected expression before ‘int’
../../userprog/syscall.c:85:17: error: expected expression before ‘int’
../../userprog/syscall.c:87:17: error: expected expression before ‘int’
../../userprog/syscall.c:89:17: error: expected expression before ‘void’
../../userprog/syscall.c:91:17: error: expected expression before ‘unsigned’

I was under the impression that void* is the only instance of polymorphism in the language and that it can point to anything. However, it appears that I'm wrong.

So which is the type of the pointer which can store the address of any function type?

Also, can you give me a good reference about C polymorphism? I've looked in many books but as far as I've seen the polymorphism chapter is very thin.

Thank you.

like image 412
octavian Avatar asked Dec 03 '22 20:12

octavian


1 Answers

Yes, you are wrong.

void * pointers can point at any kind of data, but in C code (functions) are not data.

It's not valid to even cast between void * and function pointers: even though on most contemporary computers it will work as expected, the language does not guarantee that.

I don't understand from your code how you intended the "overloading" to be used in practice, how do you expect to call through the foo pointer? Just having the expected number of arguments is not enough, arguments have types and thus are handled differently in the function call.

like image 162
unwind Avatar answered Dec 31 '22 21:12

unwind