struct accessor实现for c

这段时间看tgt源码,遇到个很闹心的问题:“找不到”函数声明和定义,但是make却不报错。

经过好几个星期,偶然发现了它的藏身之所,跟老师学习了一下,方知有这样的惯用写法,特此mark一下备忘。

1. 先看调用处代码,红色函数找不到定义:

static int iscsi_target_cmd_queue(struct iscsi_task *task)
{
	struct scsi_cmd *scmd = &task->scmd;
	struct iscsi_connection *conn = task->conn;
	struct iscsi_cmd *req = (struct iscsi_cmd *) &task->req;
	uint32_t data_len;
	uint8_t *ahs;
	int ahslen;
	int err;
	enum data_direction dir = scsi_get_data_dir(scmd);

	......

	data_len = ntohl(req->data_length);
	/* figure out incoming (write) and outgoing (read) sizes */
	if (dir == DATA_WRITE || dir == DATA_BIDIRECTIONAL) {
		scsi_set_out_length(scmd, data_len);
		scsi_set_out_buffer(scmd, task->data);
	} else if (dir == DATA_READ) {
		scsi_set_in_length(scmd, data_len);
		scsi_set_in_buffer(scmd, task->data);
	}

}

2. 在另一个头文件中,有如下宏定义:

struct scsi_cmd {
	struct target *c_target;
	/* linked it_nexus->cmd_hash_list */
	struct list_head c_hlist;
	struct list_head qlist;

	uint64_t dev_id;

	struct scsi_lu *dev;
	unsigned long state;

	enum data_direction data_dir;
	struct scsi_data_buffer in_sdb;
	struct scsi_data_buffer out_sdb;

	uint64_t cmd_itn_id;
	uint64_t offset;
	uint32_t tl;
	uint8_t *scb;
	int scb_len;
	uint8_t lun[8];
	int attribute;
	uint64_t tag;
	int result;
	struct mgmt_req *mreq;

	unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
	int sense_len;

	struct list_head bs_list;

	struct it_nexus *it_nexus;
	struct it_nexus_lu_info *itn_lu_info;
};

#define scsi_cmnd_accessor(field, type)						\
static inline void scsi_set_##field(struct scsi_cmd *scmd, type val)		\
{										\
	scmd->field = val;							\
}										\
static inline type scsi_get_##field(struct scsi_cmd *scmd)			\
{										\
	return scmd->field;							\
}

scsi_cmnd_accessor(result, int);
scsi_cmnd_accessor(data_dir, enum data_direction);


#define scsi_data_buffer_accessor(field, type, set_cast, get_cast)		\
	scsi_data_buffer_function(in, field, type, set_cast, get_cast)		\
	scsi_data_buffer_function(out, field, type, set_cast, get_cast)

#define scsi_data_buffer_function(dir, field, type, set_cast, get_cast)		\
static inline void scsi_set_##dir##_##field(struct scsi_cmd *scmd, type val)	\
{										\
	scmd->dir##_sdb.field = set_cast (val);					\
}										\
static inline type scsi_get_##dir##_##field(struct scsi_cmd *scmd)		\
{										\
	return get_cast (scmd->dir##_sdb.field);				\
}

scsi_data_buffer_accessor(length, uint32_t, ,);
scsi_data_buffer_accessor(transfer_len, uint32_t, ,);
scsi_data_buffer_accessor(resid, int32_t, ,);
scsi_data_buffer_accessor(buffer, void *, (unsigned long), (void *)(unsigned long));


3. 将此宏展开来之后,总算是找到函数定义了:

gcc -E usr/scsi_cmnd.h -o temp.h

less temp.h:

static inline void scsi_set_result(struct scsi_cmd *scmd, int val) { 
	scmd->result = val; 
} 
static inline int scsi_get_result(struct scsi_cmd *scmd) {
	return scmd->result; 
};
static inline void scsi_set_data_dir(struct scsi_cmd *scmd, enum data_direction val) { 
	scmd->data_dir = val; 
} 
static inline enum data_direction scsi_get_data_dir(struct scsi_cmd *scmd) { 
	return scmd->data_dir; 
};

static inline void scsi_set_in_length(struct scsi_cmd *scmd, uint32_t val) { 
	scmd->in_sdb.length = (val); 
} 
static inline uint32_t scsi_get_in_length(struct scsi_cmd *scmd) { 
	return (scmd->in_sdb.length); 
} 
static inline void scsi_set_out_length(struct scsi_cmd *scmd, uint32_t val) { 
	scmd->out_sdb.length = (val); 
} 
static inline uint32_t scsi_get_out_length(struct scsi_cmd *scmd) { 
	return (scmd->out_sdb.length); 
};
static inline void scsi_set_in_transfer_len(struct scsi_cmd *scmd, uint32_t val) { 
	scmd->in_sdb.transfer_len = (val); 
} 
static inline uint32_t scsi_get_in_transfer_len(struct scsi_cmd *scmd) { 
	return (scmd->in_sdb.transfer_len); 
} 
static inline void scsi_set_out_transfer_len(struct scsi_cmd *scmd, uint32_t val) { 
	scmd->out_sdb.transfer_len = (val); 
} 
static inline uint32_t scsi_get_out_transfer_len(struct scsi_cmd *scmd) { 
	return (scmd->out_sdb.transfer_len); 
};
static inline void scsi_set_in_resid(struct scsi_cmd *scmd, int32_t val) { 
	scmd->in_sdb.resid = (val); 
} 
static inline int32_t scsi_get_in_resid(struct scsi_cmd *scmd) { 
	return (scmd->in_sdb.resid); 
} 
static inline void scsi_set_out_resid(struct scsi_cmd *scmd, int32_t val) { 
	scmd->out_sdb.resid = (val); 
} 
static inline int32_t scsi_get_out_resid(struct scsi_cmd *scmd) { 
	return (scmd->out_sdb.resid); 
};
static inline void scsi_set_in_buffer(struct scsi_cmd *scmd, void * val) { 
	scmd->in_sdb.buffer = (unsigned long) (val); 
} 
static inline void * scsi_get_in_buffer(struct scsi_cmd *scmd) { 
	return (void *)(unsigned long) (scmd->in_sdb.buffer); 
} 
static inline void scsi_set_out_buffer(struct scsi_cmd *scmd, void * val) { 
	scmd->out_sdb.buffer = (unsigned long) (val); 
} 
static inline void * scsi_get_out_buffer(struct scsi_cmd *scmd) { 
	return (void *)(unsigned long) (scmd->out_sdb.buffer); 
};


4.总结一下,关键的宏定义如下:

#define scsi_cmnd_accessor(field, type)						\
static inline void scsi_set_##field(struct scsi_cmd *scmd, type val)		\
{										\
	scmd->field = val;							\
}										\
static inline type scsi_get_##field(struct scsi_cmd *scmd)			\
{										\
	return scmd->field;							\
}


这里定义了一个成员的get和set函数,通过宏参数将成员名和成员类型传入。

然后通过宏调用来为result和data_dir两个字段生成getter和setter:

scsi_cmnd_accessor(result, int);
scsi_cmnd_accessor(data_dir, enum data_direction);


后续需要增加其他字段时,只需修改struct,增加新字段的宏调用,即可很方便的生成getter和setter。

很赞的方法!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值