C (void *) used as a pointer to a polymorphic function

I am trying to create a system call handler and I am not sure how to save it.

I use the following typedefto store a pointer (void *)that should get the address of the function and an integer arg_norepresenting 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 am trying to initialize an array as follows.

  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 assignments of the function pointer to the void pointer lead to 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 got the impression that it void*is the only instance of polymorphism in the language and that it can indicate anything. However, it seems that I'm wrong.

So what is the type of pointer that can hold the address of any type of function?

, ? , , , .

.

+4
6

, .

void * , C- () .

void * : , , .

, "" , foo? , , , - .

+6

, , void *:

ish[0].foo  = (void *)halt;

C , , void *; , POSIX , , .

+5

. . .

void (*halt) (void) = halt_sys_call_function;
ish[0].foo  = &halt; ish[0].arg_no  = 0;

C , , . C. , C.

+2

, :

typedef struct 
{

  void     (*halt) (void);                  
  void     (*exit) (int status);  
  pid_t    (*exec) (const char *file);      
  int      (*wait) (pid_t);                 
  bool     (*create) (const char *file, unsigned initial_size);
  bool     (*remove) (const char *file);    
  int      (*open) (const char *file);      
  int      (*filesize) (int fd);            
  int      (*read) (int fd, void *buffer, unsigned length);
  int      (*write) (int fd, const void *buffer, unsigned length);  
  void     (*seek) (int fd, unsigned position);   
  unsigned (*tell) (int fd);                

} myFuncs;

, void*, void *addressOfWait = (void*)&wait;, :

int (*waitFunctionPointer)(pid_t) = addressOfWait;

:

waitFunctionPointer((pid_t) 1111); //wait for process with pid of 1111
+1

@problemPotato :

typedef struct 
{
   void     (*halt) (void);                  
   void     (*exit) (int status);  
   pid_t    (*exec) (const char *file);      
   int      (*wait) (pid_t);                 
   bool     (*create) (const char *file, unsigned initial_size);
   bool     (*remove) (const char *file);    
   int      (*open) (const char *file);      
   int      (*filesize) (int fd);            
   int      (*read) (int fd, void *buffer, unsigned length);
   int      (*write) (int fd, const void *buffer, unsigned length);  
   void     (*seek) (int fd, unsigned position);   
   unsigned (*tell) (int fd);                
} fs_ops;

, , :

int      ext5_open(const char * file);
unsigned ext5_tell (int fd);

( ):

fs_ops ext5_ops = {
   .open = ext5_open,
   .tell = ext5_tell,
};

, , NULL (.. ). , , (if(ext5_ops.seek == NULL) ...), :

retval = ext5_ops.(*ext5_open)("/tmp/junk");

(parenteses (*ext5_open) , * (-) , ).

+1

void *, , . union. - , . , user4815162342 , , , enum.

typedef struct
{
  union {
    void *vp;
    void (*v__v)(void);
    void (*v__i)(int);
    pid_t (*pid__ccp)(const char *);
    int (*i__pid)(pid_t);
    bool (*b__ccp_u)(const char *, unsigned);
    bool (*b__ccp)(const char *);
    int (*i__ccp)(const char *);
    int (*i__i)(int);
    int (*i__i_vp_u)(int, void *, unsigned);
    int (*i__i_cvp_u)(int, const void *, unsigned);
    void (*v__i_u)(int, unsigned);
    unsigned (*u__i)(int);
  } fp;
  int arg_no;
}td_sys_call_handler;

, , "-". , .

. , - , X-Macros. : .

#define function_types(_) \
    _(v__v, void, void) \
    _(v__i, void, int) \
    _(pid_ccp, pid_t, const char *) \
    _(i__pid, int, pid_t) \
    _(b__ccp_u, const char *, unsigned) \
    _(b__ccp, const char *) \
    _(i__ccp, const char *) \
    _(i__i, int) \
    _(i__i_vp_u, int, void *, unsigned) \
    _(i__i_cvp_u, int, const void *, unsigned) \
    _(v__i_u, int, unsigned) \
    _(u__i, unsigned, int) \
    /* end function_types */

"" -macro , , , _, .

, , _ :

#define create_function_pointer(id, ret, ...) \
    ret (*id)(__VA_ARGS__);

#define create_function_type_id(id, ret, ...) \
    f__ ## id

typedef struct {
    union {
        void *vp;
        function_types(create_function_pointer)
    } fp;
    int arg_no;
    enum {
        function_types(create_function_type_id)
    } type;
} td_sys_call_handler;

:

td_sys_call_handler ish[SYSCALL_HANDLER_NUM];
int i=0;

ish[i++]  = (td_sys_call_handler){ halt,     0, f__v__v };
ish[i++]  = (td_sys_call_handler){ exit,     1, f__v__i };
ish[i++]  = (td_sys_call_handler){ exec,     1, f__pid__ccp };
ish[i++]  = (td_sys_call_handler){ wait,     1, f__i__pid };
ish[i++]  = (td_sys_call_handler){ create,   2, f__b__ccp_u };
ish[i++]  = (td_sys_call_handler){ remove,   1, f__b__ccp };
ish[i++]  = (td_sys_call_handler){ open,     1, f__i__ccp };
ish[i++]  = (td_sys_call_handler){ filesize, 1, f__i__i };
ish[i++]  = (td_sys_call_handler){ read,     3, f__i__i_vp_u };
ish[i++]  = (td_sys_call_handler){ write,    3, f__i__i_cvp_u };
ish[i++]  = (td_sys_call_handler){ seek,     2, f__v__i_u };
ish[i++]  = (td_sys_call_handler){ tell,     1, f__u__i };

, , ( ) a switch, . stdarg .

void make_sys_call(td_sys_call_handler ish, ...){
    va_list ap;
    int i;
    const char *ccp;
    pid_t pid;
    bool b;
    void *vp;
    unsigned u;
    const void *cvp;
    va_start(ap, ish);
    switch(ish.type) {
    case f__v__f: ish.fp.v__v();
                  break;
    case f__v__i: i = va_arg(int);
                  ish.fp.v__i(i);
                  break;
    case f__pid__ccp: ccp = va_arg(const char *);
                      ish.fp.pid__ccp(ccp);
                      break;
    // etc.
    }
    va_end(ap);
}

. union, , , - . . .

.

+1

Source: https://habr.com/ru/post/1530632/


All Articles