Search code examples
cadtinformation-hiding

How to achieve information hiding in this case?


I learnt that ADT is an important concept and I'm learning this tech.

Here is a problem that I don't know how to deal with.

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*/
}

Now, I don't want else files to know type "ATEIS_Payload_s", except for functions in Payload_Manager.c. Because only functions in Payload_Manager.c deal with type "payload".

In other words, I want to change code in CmdHndlr.c to:

//#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*/
}

Here is a thing worthy noted: function "DNM_Manager_Ctor" deals with type "DNM" and "ATEIS_Payload_s" at the same time.

It's achieved by letting DNM_Manager_Ctor know both type "DNM" and "ATEIS_Payload_s". Meaning that changing DNM_Manager.c to:

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;
}

I don't know whether this way is valid. But this way will clearly decrease modularity, even it's valid.

Is there any better way to solve it?

edit:

I'm new to object oriented. I'm trying to implement this concept in C although it's very rough. Also, it's highly likely that I misused this concept in this program.


Solution

  • You're shooting at the wrong target.

    Your objective shouldn't be to turn every pointer into void*, because in that way you're giving up all the (limited) type safety that the C compiler can provide.

    Instead, your objective should be to hide the definition (that is, the internals) of the structs to the clients.

    How to do so is explained in this article.