我隐藏了 struct 类型中的一些结构字段,以使公共(public) API header 更加清晰。
首先,我使用这种样式来隐藏(实际上不是隐藏,只是与公共(public)可编辑成员分开)一些成员,
include/scene.h
typedef struct ScenePrivateFields {
SceneFlags flags;
/* other members */
} ScenePrivateFields;
typedef struct Scene {
ScenePrivateFields _priv;
RootNode rootNode;
/* other members */
} Scene;
对于这种风格,我总是在函数参数中使用场景类型,然后使用 _priv 成员访问私有(private)字段。但是将所有私有(private)字段保留在公共(public) header 中会使 header 变得更加复杂
最后我换了另一种风格
include/scene.h
typedef struct Scene {
RootNode rootNode;
/* other members */
} Scene;
EXPORT
Scene*
allocScene(void);
src/types/impl_scene.h
typedef struct SceneImpl {
Scene pub;
SceneFlags flags;
/* other members */
} SceneImpl;
例如,如果我有这样的函数:
include/scene.h
void
renderScene(Scene * __restrict scene, /* other params */);
我必须将场景转换为 SceneImpl 才能访问私有(private)字段。我这样做是这样的:
src/scene/scene.c
void
renderScene(Scene * __restrict scene, /* other params */) {
SceneImpl *sceneImpl;
sceneImpl = (SceneImpl *)scene;
}
为了避免强制转换每个函数调用,我想也许我可以做这样的事情,如果它是合法的并且不违反 C 标准:
src/scene/scene.c
void
renderScene(SceneImpl * __restrict sceneImpl, /* other params */) {
/* skip casting scene to sceneImpl */
}
由于Scene是SceneImpl的第一个成员,我可以用Scene定义公共(public)api(函数)并用SceneImpl定义实现(函数)吗?我认为它会起作用,因为两者都是指针,这是有效的还是好主意?
注意:我使用 -fstrict-aliasing 进行编译
编辑:FWIW,这里是分配函数实现,用户必须使用此函数来分配结构:
EXPORT
Scene*
allocScene(void) {
SceneImpl *sceneImpl;
sceneImpl = calloc(1, sizeof(*sceneImpl));
/* initialize pulic part */
sceneImpl->pub.field1 = ...
/* initialize private part */
sceneImpl->priv_field1 = ...
/* return public part */
return &sceneImpl->pub;
}
最佳答案
您可以使用不透明类型作为数据的私有(private)部分。
在公共(public) header 中,定义结构如下:
// forward declaration of struct ScenePrivateFields
typedef struct ScenePrivateFields ScenePrivateFields;
typedef struct Scene {
ScenePrivateFields *_priv; // now a pointer
RootNode rootNode;
/* other members */
} Scene;
然后在您的实现文件中,定义私有(private)结构:
struct ScenePrivateFields {
SceneFlags flags;
/* other members */
}
您还需要定义一个函数,该函数动态创建 struct ScenePrivateFields
的实例并返回指向它的指针以填充公共(public)结构中的指针。
关于c - 函数参数类型兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47518485/