2016-03-05 46 views
0

我正在開發一個數據庫訪問層來存儲軟件子系統的數據。數據庫接口有兩個功能,database_get()database_set()。它們有兩個參數,第一個是標識軟件組件的標識,第二個參數是一個typedef結構,用於保存此軟件組件的新設置。那麼我:僅使用一個函數更新全局C結構而不傳遞整個數據結構

#define COMPONENT1_ID 7 
typedef struct 
{ 
    int member1; 
    char member2; 
    char member3; 

} COMPONENT1_STRUCT_T ; 

我可以存儲和檢索持久數據調用database_set(COMPONENT1_ID, (void *) &new_struct)database_get(COMPONENT1_ID, (void *) &new_struct)功能。它與使用此數據庫的任何其他軟件子系統存儲數據的工作原理相同。

現在我正在開發API來管理這個軟件子系統。這些API由用戶界面使用。軟件子系統的API負責執行組件背後的所有邏輯,並且還調用數據庫使其數據持久化。我制定了關於執行該操作的API函數,最後調用這樣的功能:

int save_new_member1_db(int member1); 
{ 
    COMPONENT1_STRUCT_T new_setting; 

    database_get(COMPONENT1_ID, (void *)&new_setting); 
    new_setting.member1 = member1; 
    database_set(COMPONENT1_ID, (void *)&new_setting); 
} 

我不知道如果我能避免產生新的功能來更新數據庫中的每個成員的數據。

另外我不想要一個大功能採取整個結構或結構的所有成員,如果它意味着子系統API被減少到一個功能。該子系統可以是LED顯示器及其API可能是不同的方法做一件事作爲update_led_display_color(常量LED_DISPLAY_COLOR新的顏色),update_led_display_font(const LED_DISPLAY_FONT cur_font)get_led_display_font(LED_DISPLAY_FONT *cur_font) ...

回答

0

您將需要某種映射代表符號常量之間成員和您需要設置該成員的信息。你可以使用像你的「COMPONENT1_ID」的每個成員,並有大小的數組+像這樣每個成員偏移信息:

#include <stdio.h> 
#include <stddef.h> 
#include <string.h> 

// in header file (or wherever so that it is visible to 
// the definition of "Test_save_member" and not a part of 
// the subsystem API) 
#define TEST_ID 7 


// in a c file (in your database implementation, I assume) 
typedef struct 
{ 
    int mem1; 
    char mem2; 
    char mem3; 
} Test; 

// for sure in header file exposed in your subsystem API 
typedef enum 
{ 
    MEM1, 
    MEM2, 
    MEM3, 
    NUM_MEMBERS 
} TestMember; 

// in c file (in your database implementation, I assume again) 

typedef struct 
{ 
    size_t offset; 
    size_t size; 
} MemberInfo; 

static MemberInfo member_info[NUM_MEMBERS] = 
{ 
    { offsetof(Test, mem1), sizeof(int) }, 
    { offsetof(Test, mem2), sizeof(char) }, 
    { offsetof(Test, mem3), sizeof(char) } 
}; 

// also a part of your subsystem API 
int Test_save_member(TestMember member, void* value) 
{ 
    if (!value || member < 0 || member >= NUM_MEMBERS)) 
     return 0; 

    Test new_setting; 
    database_get(TEST_ID, (void *)&new_setting); 
    MemberInfo info = member_info[member]; 
    memcpy((char*)(&new_setting) + info.offset, value, info.size); 
    database_set(TEST_ID, (void *)&new_setting); 
    return 1; 
} 

// subsystem API usage 
int main(void) 
{ 
    int new_mem1 = 5; 
    Test_save_member(MEM1, &new_mem1); 
    return 0; 
} 

取決於是否要修改你的數據庫功能,連接你的量想要處理等,這可能會發生巨大的變化;但是,我不認爲,如果考慮到您提到的限制,您可以不使用某種類型的映射。

這個特定的實現將不允許傳遞文字,但這不應該是一個問題太大(處理或解決)。

+1

太棒了!我認爲唯一的解決方案就是這種方式或者其他任何看起來像這樣的方法,通過表驅動方法處理成員的偏移量和大小。 – MABC