我有一个带有基于回调的 C API 的 c++ 库。回调类型如下所示:
typedef struct {...} Result;
typedef void (*callback) (const Result* result, void* userData);
用户可以像这样注册一个回调,并可以设置一个指向任意数据的指针,库将通过回调将该指针传回。
我主要关心的是:它是否违反了严格的别名规则?我需要将 userData 的类型更改为 char* 吗?
我有一个带有基于回调的 C API 的 c++ 库。回调类型如下所示:
typedef struct {...} Result;
typedef void (*callback) (const Result* result, void* userData);
用户可以像这样注册一个回调,并可以设置一个指向任意数据的指针,库将通过回调将该指针传回。
我主要关心的是:它是否违反了严格的别名规则?我需要将 userData 的类型更改为 char* 吗?
不,别名仅适用于间接指针时,而不是当它们作为指针值传递时。只要用户的行为始终如一,你就会没事的。
也就是说,用户必须确保如果他们传递userData
的是实际类型T
,那么他们总是T *
在访问它之前将其强制转换为回调函数。
我当然假设您没有userData
在您的库中进行间接访问,尽管再次将其作为指针访问(例如printf("DEBUG: %p", userData)
)就可以了。
您可以为 C 回调 API 创建一个更像“C++”的接口,这可能会消除您的别名问题。
struct Callback {
void (*callback) (Callback *cb_this, const Result *result);
};
使用 C 回调 API 注册回调的 AC 程序员会执行以下操作:
struct MyCallback {
struct Callback cb;
int x;
double y;
/* ... */
};
void my_callback_func (Callback *cb_this, const Result *result) {
MyCallback *my_cb = (MyCallback *)cb_this;
/* ... */
}
MyCallback mycb = { { my_callback_func }, 0, 0, /* ... */ };
这样您就不必担心处理void *
. 相反,您将获得一个指向Callback
.