【发布时间】:2015-01-04 22:40:03
【问题描述】:
我有一个 C 项目,旨在移植到各种(PC 和嵌入式)平台。
应用程序代码将使用各种调用,这些调用具有特定于平台的实现,但共享一个通用(通用)API 以帮助实现可移植性。我正在尝试选择最合适的方式来声明函数原型和结构。
这是我到目前为止的想法:
main.c:
#include "generic.h"
int main (int argc, char *argv[]) {
int ret;
gen_t *data;
ret = foo(data);
...
}
generic.h:(与平台无关的包含)
typedef struct impl_t gen_t;
int foo (gen_t *data);
impl.h:(特定于平台的声明)
#include "generic.h"
typedef struct impl_t {
/* ... */
} gen_t;
impl.c:(特定于平台的实现)
int foo (gen_t *data) {
...
}
构建:
gcc -c -fPIC -o platform.o impl.c
gcc -o app main.c platform.o
现在,这似乎可以工作......因为它可以编译。但是,我通常不会标记我的结构,因为它们从未在 typedef'd 别名之外访问过。这是一个小小的挑剔,但我想知道是否有办法使用匿名结构实现相同的效果?
我也在问后人,因为我搜索了一段时间,我找到的最接近的答案是:(Link)
在我的情况下,这不是正确的方法,因为应用程序不应该直接包含实现头文件——重点是将程序与平台分离。
我看到了其他一些不太理想的方法来解决这个问题,例如:
generic.h:
#ifdef PLATFORM_X
#include "platform_x/impl.h"
#endif
/* or */
int foo (struct impl_t *data);
这些似乎都不是特别吸引人,而且绝对不是我的风格。虽然我不想逆流而上,但当可能有更好的方法来实现我的想法时,我也不想要冲突的风格。所以我认为 typedef 解决方案是在正确的轨道上,它只是我留下的 struct tag 包袱。
想法?
【问题讨论】:
-
您可以将
gen_t设为指针类型(句柄)。然后客户端将不得不使用您的 api 来初始化/使用/销毁它。或稍作变化,使您公开的结构包含指向实际实现的不透明指针。否则,您无能为力。必须创建客户端必须知道的对象或路径跟踪它。 -
存在一个问题,即在 impl.h 之前包含 generic.h 但是,generic.h 引用了 impl.h I.E 中定义的结构。前向参考。 (可能不会编译)更好地让 generic.h 包含 impl.h(其中 impl.h 是特定于平台的)然后当 generic.h 尝试使用它时,结构将已经定义。
-
最好将结构定义为: struct tagname { ;;; };然后始终将其引用为 'struct tagname myname;'造成这种情况的原因有很多:1)命名结构是一种已弃用的格式 2)调试器使用标签名称来引用字段等 3)在结构上使用 typedef(通常)是不好的编程习惯
标签: c portability