【发布时间】:2019-06-20 20:47:46
【问题描述】:
我已经定义了接口:
typedef DataExchg_Status_T (*DataExchg_Iface_ReceiveDataClbk_T)(
void * p_self, uint8_t const * p_data, size_t size);
typedef struct DataExchg_Iface_Tag {
DataExchg_Status_T (*SendData)(void * p_self, uint8_t const * p_data, size_t size);
void (*RegisterReceiveDataClbk)(void * p_self,
DataExchg_Iface_ReceiveDataClbk_T receive_data_clbk,
void * p_receiver_instance);
void * pSelf;
} DataExchg_Iface_T;
我在Object_A 中使用它。
typedef struct Object_A_Tag {
DataExchg_Iface_T * pIface;
} Object_A_T;
在Object_B 模块中
我已经实现了这个接口:
typedef struct Object_B_Tag {
int value;
...
} Object_B_T;
DataExchg_Status_T SendData(Object_B_T * p_self, uint8_t const * p_data, size_t size) {
...
}
void RegisterReceiveDataClbk(Object_B_T * p_self,
DataExchg_Iface_ReceiveDataClbk_T receive_data_clbk,
void * p_receiver_instance) {
...
}
一切正常,直到我想将上述函数分配给 Object_A 中的接口:
Object_B object_b = {...};
Object_A object_a = {
.pIface = &(DataExchg_Iface_T){
.SendData = SendData,
.RegisterReceiveDataClbk = RegisterReceiveDataClbk,
.pSelf = &object_b
}
};
问题是我收到不兼容的指针警告,因为参数之一:void * p_self 在接口实现中不等于Object_B_T * p_self。
这个问题有一些可能的解决方案:
1.转换为接口函数指针:
SendData = (DataExchg_Status_T(*)(void *, DataExchg_Iface_ReceiveDataClbk_T, void *)SendData
这是最方便的解决方案,但有一些强有力的证据表明此解决方案可能导致未定义的行为:Casting a function pointer to another type
2。完全按照声明实现接口并在函数体中转换参数:
这是最安全的解决方案,但不是最方便的。
DataExchg_Status_T SendData(void * p_self, uint8_t const * p_data, size_t size) {
Object_B_T pSelf = p_self;
}
3.初始化接口时转换为接口函数指针(方案一),每次使用时都将接口函数转换为它的实现类型:
据我所知,此解决方案不应导致未定义的行为。
object_b.pIface->(DataExchg_Status_T(*)(Object_B *, DataExchg_Iface_ReceiveDataClbk_T, void *)SendData(...)
最后是问题:
1) 在我的情况下,解决方案 1 真的会导致未定义的行为吗?
2) 有什么解决方案可以让我使用 void 实例指针进行通用接口声明,并使用特定实例指针进行特定实现? (类似于方案一)
【问题讨论】:
标签: c casting function-pointers