Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hiding internal type [duplicate]

Tags:

c

embedded

I want to hide the internal type from the user of a library.
Currently I have something like this:

foo.h

typedef struct public
{
    uint16 a;
    //...
    unsigned char internals[4];
} public_type;

foo.c

typedef struct public
{
    uint32_t a;
}internals_type;

Then in the functions, I'm doing a cast like.

void bar(public_type * const public_struct)
{
     internals_type* const internals = &public_struct->internals;
     intrnals->a = getSomething();
     // .....
}

Is there a better way of doing this?

I've tried some weird stuff with unions and pointers in the header, but nothing seems to be better and I'm curious if this can get any cleaner or at least if the warnings from casting a pointer from one type to pointer to another could be removed.

like image 229
Petar Velev Avatar asked Oct 16 '18 12:10

Petar Velev


1 Answers

I suggest you read more about opaque data types, and consider e.g. the FILE structure.

In short, don't split your structure into "public" and "private" variants (that way lies madness and possible undefined behavior). Instead just declare a structure in a public header file, and have your functions return pointers to that structure or accept arguments that are pointers to that structure.

Then internally in the library you have a private header file which have the definition of the structure, and use that header file for your implementation.


Simple example

Public header file

#ifndef PUBLIC_HEADER_FILE_H
#define PUBLIC_HEADER_FILE_H

typedef my_private_structure MY_PUBLIC_TYPE;

MY_PUBLIC_TYPE *mylib_create(void);
void mylib_destroy(MY_PUBLIC_TYPE *ptr);

#endif

Private header file

#ifndef PRIVATE_HEADER_FILE_H
#define PRIVATE_HEADER_FILE_H

#include "public_header_file.h"

struct my_private_structure
{
    // Some private fields here
};

#endif

Private library source file

#include "private_header_file.h"
#include <stdlib.h>

MY_PUBLIC_TYPE *mylib_create(void)
{
    MY_PUBLIC_TYPE *ptr = malloc(sizeof *ptr);
    return ptr;
}

void mylib_destroy(MY_PUBLIC_TYPE *ptr)
{
    free(ptr);
}

You distribute public_header_file.h together with your library. It's the header file that the users of the library will use.

The source of your library, and especially the private_header_file.h file should not be distributed, or at least not installed if you make an open-source library.

Note that this scheme make all of the structure "private", which is usually a good idea since then you can modify it as you like without the users of the library needing to rebuild their applications using your library. To access members of the private structure you can use functions which simply returns the value of whatever member needs to be accessed.

like image 79
Some programmer dude Avatar answered Oct 12 '22 00:10

Some programmer dude