Как добиться сокрытия информации в этом случае? - PullRequest
0 голосов
/ 12 января 2019

Я узнал, что ADT является важной концепцией, и я изучаю эту технологию.

Вот проблема, с которой я не знаю, как справиться.

Payload_Manager.h

typedef struct __attribute__((__packed__))
{
    u32 Addr;
    u16 Cmd;
    u16 Len;
    u8 Data[0];
}ATEIS_Payload_s;   //payload

Payload_Manager.c

#include "Payload_Manager.h"
void* Payload_Manager_New(int size)
{
    return (ATEIS_Payload_s*)malloc(size);
}
void* Payload_Manager_Ctor(void* _this, u32 ip, u16 cmdID, u16 dataLen, char* rxBuf)
{
    ATEIS_Payload_s* this = (ATEIS_Payload_s*)_this;
    this->Addr = ip;
    this->Cmd = cmdID;
    this->Len = dataLen;
    memcpy(this->Data, rxBuf, dataLen);
    return this;
}
void* Payload_Manager_Dtor(void** _this)
{
    free(*_this);
    *_this = NULL;
    return *_this;
}

DNM_Manager.h

void* DNMManager_Ctor(void* _this,
                      void* name, 
                      u32 ip, 
                      u32 sn, 
                      u32 subMask);

DNM_Manager.c

typedef struct
{
    u32 Addr;
    u32 SerialNo;
    u32 SubnetMask;
    char Name[NAME_SIZE];
}DNM;

static DNM DNMSet[SET_SIZE];
static DNM DNMTemp;

void* DNMManager_Ctor(void* _this, 
                      void* name, 
                      u32 ip, 
                      u32 sn, 
                      u32 subMask)
{
    DNM* this = (DNM*)_this;
    memcpy(this->Name, name, NAME_SIZE);
    this->Addr = ip;
    this->SerialNo = sn;
    this->SubnetMask = subMask;
    return this;
}

CmdHndlr.c

#include "Payload_Manager.h"
#include "DNM_Manager.h"
int main(void){
    ATEIS_Payload_s* pl_p = NULL;
    void* DNM_temp = NULL;

    pl_p = OSTaskQPend(0, OS_OPT_PEND_BLOCKING, &msgSize, &ts, &err);   //wait for a message

    /*This works properly*/
    DNM_temp = DNMManager_Ctor(DNM_temp,
                               &pl_p->Data[NAME],
                               pl_p->Addr,
                               *(u32*)&pl_p->Data[SN],
                               *(u32*)&pl_p->Data[SUBMASK]);
    /*following code is omitted*/
}

Теперь я не хочу, чтобы другие файлы знали тип "ATEIS_Payload_s", за исключением функций в Payload_Manager.c. Потому что только функции в Payload_Manager.c имеют дело с типом «полезная нагрузка».

Другими словами, я хочу изменить код в CmdHndlr.c на:

//#include "Payload_Manager.h"    /*no need anymore*/
#include "DNM_Manager.h"
int main(void){
    void* pl_p = NULL;    //programmer no need to know what type pl_p is
    void* DNM_temp = NULL;

    pl_p = OSTaskQPend(0, OS_OPT_PEND_BLOCKING, &msgSize, &ts, &err);   //wait for a message

    DNM_temp = DNMManager_Ctor(DNM_temp, pl_p);    //DNM_Manager_Ctor will deal with it.
    /*following code is omitted*/
}

Здесь стоит отметить: функция «DNM_Manager_Ctor» обрабатывает типы «DNM» и «ATEIS_Payload_s» одновременно.

Это достигается тем, что DNM_Manager_Ctor знает оба типа "DNM" и "ATEIS_Payload_s". Это означает, что изменение DNM_Manager.c на:

typedef struct
{
    u32 Addr;
    u32 SerialNo;
    u32 SubnetMask;
    char Name[NAME_SIZE];
}DNM;
typedef struct __attribute__((__packed__))    //oops, already declared in somewhere else. Is this valid?
{
    u32 Addr;
    u16 Cmd;
    u16 Len;
    u8 Data[0];
}ATEIS_Payload_s;   //payload

void* DNMManager_Ctor(void* _this, 
                      void* _dest)
{
    DNM* this = (DNM*)_this;
    ATEIS_Payload_s* dest = (ATEIS_Payload_s*)_dest;

    /*following is omitted*/

    return result;
}

Я не знаю, допустим ли этот способ. Но этот способ явно уменьшит модульность, даже если он действителен.

Есть ли лучший способ решить это?

редактирование:

Я новичок в объектно-ориентированном. Я пытаюсь реализовать эту концепцию в C, хотя это очень грубо. Кроме того, весьма вероятно, что я неправильно использовал эту концепцию в этой программе.

Ответы [ 2 ]

0 голосов
/ 12 января 2019

Ваш пример очень длинный, поэтому я постараюсь помочь вам получить представление о сокрытии информации и рекламе.

когда речь идет об информации, скрывающей то, что нужно иметь в виду, это то, что если вы предоставите внешнему пользователю свой h-файл, он сможет использовать ваши c-функции без знания того, как кодер "сделал это", например, в ваш Payload_Manager.h пользователю не нужно знать, как строится структура. единственное, что ему нужно от этой модели - это функциональность, которую он дает. Таким образом, правильный способ написать этот h-файл - это сначала переместить структуру в ваш c-файл и поместить только typedef этой структуры в ваш h-файл:

struct __attribute__((__packed__)) ATEIS_Payload_s
{
u32 Addr;
u16 Cmd;
u16 Len;
u8 Data[0];
};

и в вашем файле h:

typedef struct ATEIS_Payload_s ATEIS_Payload_s;

Я не уверен, почему ваша функция create возвращает (void *). думаю об этом. если пользователь использует функцию void * Payload_Manager_Ctor - он хочет получить полезную нагрузку. Кроме того, вы должны объявить все статические функции, предназначенные для пользователя, в вашем файле c в файле h так что теперь они могут использоваться по назначению внешним пользователем.

В двух словах, файл H должен иметь только то, что ДОЛЖЕН иметься для использования функциональных возможностей, но не рецепт того, как они делают то, что делают.

Теперь о абстрактных типах данных, идея их использования для случаев, когда единственным, кому нужно знать, кто они, является пользователь.

Подумайте о простом связанном списке или векторе. Вы можете составить список, в котором хранится только тип данных int. но эта реализация теперь ограничивает удобство использования вашего кода. если вы создадите узел, который вместо этого несет в себе пустоту * для данных, для пользователя не будет ограничений относительно того, что может быть помещено в этот список. он может хранить указатели на структуры, массивы, символы. функциональность списка остается прежней, данные будут сохранены в списке. а что за данные? какой бы пользователь ни нуждался в этом. так как пользователь знает, что он сохранил, он будет знать, как правильно извлечь его и манипулировать им.

Надеюсь, это поможет, удачи !!

0 голосов
/ 12 января 2019

Вы стреляете не по той цели.

Ваша цель не должна состоять в том, чтобы превратить каждый указатель в void*, потому что таким образом вы отказываетесь от всей (ограниченной) безопасности типов, которую может обеспечить компилятор C.

Вместо этого ваша цель должна заключаться в том, чтобы скрыть определение (то есть внутреннее устройство) структур для клиентов.

Как это сделать, объясняется в этой статье.

...