我有一個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
的別名之外訪問。這是一個小挑戰,但我想知道是否有辦法通過匿名結構實現相同的效果?
我還要求後人,因爲我搜索了一會兒,最接近的答案,我發現是這樣的:(Link)
在我而言,這不會是正確的做法,因爲應用程序特別是不應該直接包含實現頭文件 - 整個過程就是將程序與平臺分離。
我看到一對夫婦的其他低於理想的方式來解決這個問題,例如:
generic.h:
#ifdef PLATFORM_X
#include "platform_x/impl.h"
#endif
/* or */
int foo (struct impl_t *data);
這些都不似乎特別有吸引力,絕對不是我的風格。雖然我不想在上游游泳,但當我可能有更好的方法來實現我的想法時,我也不希望發生衝突。所以我認爲typedef解決方案是正確的,它只是我留下的結構標籤行李。
想法?
你可以只讓'gen_t'指針類型(句柄)。然後客戶端將不得不使用你的api來初始化/使用/銷燬它。或者有一點變化,讓你公開的結構包含一個不透明的指向實際實現的指針。否則,你可以做的其他事情就不多了。必須創建客戶必須瞭解的對象或跟蹤方法。 – 2014-11-08 05:59:43
存在這樣一個問題是被包括BEFORE impl.h的generic.h但是,generic.h被引用在impl.h I.E.定義的結構一個前瞻性參考。 (可能不會編譯)要好得多,以使generic.h包含impl.h(其中impl.h是特定於平臺的)然後,當generic.h嘗試使用它時,該結構已經被定義。 – user3629249 2014-11-08 09:41:11
定義一個結構好得多:struct tagname {;;; };然後始終將其引用爲'struct tagname myname;'有這樣一些原因:1)命名結構是折舊格式2)調試器使用標籤名稱引用字段等3)在結構上使用typedef是(一般情況下)不好的編程練習 – user3629249 2014-11-08 09:46:00