Problem 1.

Use of a pointer to a function: error at compile time.

type defaults to ‘int’ in declaration of ‘on_touch_messgae_handle'[-Wimplicit-int] typedef(*on_touch_messgae_handle)(touch_message_t); Fan source code is as follows:

2. The analysis

1) Structure analysis

 1 struct touch_message                                                        
  2 {
  3     rt_uint16_t x;
  4     rt_uint16_t y;  
  5     rt_uint8_t event;   
  6 };
  7 typedef struct touch_message * touch_message_t;
  8 typedef (*on_touch_messgae_handle)(touch_message_t);

Copy the code

First look at the type definition in line 7:

typedef struct touch_message * touch_message_t;
Copy the code

After the definition

touch_message_t 
Copy the code

Is equivalent to

 struct touch_message *
Copy the code

That is if we define a variable with touch_message_t as a pointer to a struct touch_message type.

Let’s look at this definition in line 8:

typedef (*on_touch_messgae_handle)(touch_message_t);
Copy the code

I can replace it with the following definition

typedef (*on_touch_messgae_handle)(struct touch_message *);
Copy the code

2) Step by step

Some C language foundation is not very good friends, may not be able to see this definition at a glance, in order to make it easier for beginners to understand, let’s take a look at the following progressive definition:

int fun;
Copy the code

This is an integer variable fun;

int fun(a);
Copy the code

This is a function fun with a null return value of type int

int fun(struct touch_message *);
Copy the code

This is a fun function that takes a pointer to struct touch_message * and returns an int

The above changes are easy to understand, so let’s modify fun as follows:

int (*fun)(struct touch_message *);
Copy the code

The parentheses have the highest precedence, and once (fun) is defined this way, then fun is combined first, so fun becomes a pointer,

So what does that pointer point to? Struct touch_message * on the right, int on the left, so pointer to a function,

Struct touch_message *

Example: Assign function my_fun to function pointer fun.

int my_fun(struct touch_message *) { } int (*fun)(struct touch_message *); fun = my_fun;

The trick here is that the function name is actually an address, and the assignment must be of the same type as the function pointer.

typedef int (*fun)(struct touch_message *);
Copy the code

What about a typedef on the left? Instead of setting fun as the new type, we can use fun to define a pointer to a function of the same type as above.

For example, define a function pointer variable with a new type and assign it a value. typedef int (*fun)(struct touch_message *); int my_fun(struct touch_message *)

{}

fun fun_ptr; fun_ptr = my_fun;

I’m going to change it to touch_message_t, and I’m going to get what it looks like in the fan source code,

typedef int (*fun)(touch_message_t);
Copy the code

However, the function type defined in the fan source code lacks the description of the return value of the function, so add an int or other type to the left.

3. function Pointers

Function Pointers are used a lot in the Linux kernel,

For the character device, the kernel provides a unified interface for the various character devices. All our operations on the device are abstracted into read, write, open, close, etc., and encapsulated in the struct file_operations:


struct file_operations {
	struct module *owner;
	loff_t (*llseek) (struct file *, loff_t.int);
	ssize_t (*read) (struct file *, char __user *, size_t.loff_t *);
	ssize_t (*write) (struct file *, const char __user *, size_t.loff_t *);
	ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long.loff_t);
	ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long.loff_t);
	int (*iterate) (struct file *, struct dir_context *);
	unsigned int (*poll) (struct file *, struct poll_table_struct *);
	long (*unlocked_ioctl) (struct file *, unsigned int.unsigned long);
	long (*compat_ioctl) (struct file *, unsigned int.unsigned long);
	int (*mmap) (struct file *, struct vm_area_struct *);
	int (*open) (struct inode *, struct file *);
	int (*flush) (struct file *, fl_owner_t id);
	int (*release) (struct inode *, struct file *);
	int (*fsync) (struct file *, loff_t.loff_t.int datasync);
	int (*aio_fsync) (struct kiocb *, int datasync);
	int (*fasync) (int, struct file *, int);
	int (*lock) (struct file *, int, struct file_lock *);
	ssize_t (*sendpage) (struct file *, struct page *, int.size_t.loff_t *, int);
	unsigned long (*get_unmapped_area)(struct file *, unsigned long.unsigned long.unsigned long.unsigned long);
	int (*check_flags)(int);
	int (*flock) (struct file *, int, struct file_lock *);
	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t.unsigned int);
	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t.unsigned int);
	int (*setlease)(struct file *, long, struct file_lock **);
	long (*fallocate)(struct file *file, int mode, loff_t offset,
			  loff_t len);
	int (*show_fdinfo)(struct seq_file *m, struct file *f);
};

Copy the code

So how do we define and initialize this struct variable?

static struct file_operations hello_ops = 
{
	.open = hello_open,
	.release = hello_release,
	.read = hello_read,
	.write = hello_write,
};
Copy the code

The function is defined as follows:

static int hello_open (struct inode *inode, struct file *filep)
{
	return 0;
}
static int hello_release (struct inode *inode, struct file *filep)
{
	return 0;
}

static ssize_t hello_read (struct file *filep, char __user *buf, size_t size, loff_t *pos)
{
	return size;
}
static ssize_t hello_write (struct file *filep, const char __user *buf, size_t size, loff_t *pos)
{
	return size;
}
Copy the code

Note that function parameters and return values must be defined strictly by type in struct file_operations.