I'm hiding some struct fields from struct types to make public API headers more clear.
First I used this style to hide (not actually hide, just separate from public editable members) some members,
include/scene.h
typedef struct ScenePrivateFields {
SceneFlags flags;
/* other members */
} ScenePrivateFields;
typedef struct Scene {
ScenePrivateFields _priv;
RootNode rootNode;
/* other members */
} Scene;
with this style I always use Scene type in function parameters then accessing private fields using _priv member. But keeping all private fields in public header makes header more complex
Eventually I switched to another style
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;
for instance if I have a function like this:
include/scene.h
void
renderScene(Scene * __restrict scene, /* other params */);
I have to cast scene to SceneImpl to access private fields. I'm doing this like:
src/scene/scene.c
void
renderScene(Scene * __restrict scene, /* other params */) {
SceneImpl *sceneImpl;
sceneImpl = (SceneImpl *)scene;
}
to avoid casting every function call I thought that maybe I can do something like this, if it is legal and not violating C standards:
src/scene/scene.c
void
renderScene(SceneImpl * __restrict sceneImpl, /* other params */) {
/* skip casting scene to sceneImpl */
}
Since Scene is first member of SceneImpl, Can I define public api (function) with Scene and define implementation (function) with SceneImpl. I think it would work because both are pointer, is it valid or good idea?
NOTE: I'm compiling with -fstrict-aliasing
EDIT: FWIW, Here alloc function implementation, users must use this func to alloc struct:
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;
}