2

I want a process to expose a structure of a message, so it can be used by other processes receiving it. However, this structure includes types of arguments which are defined in other header files, which themselves include a bunch of other header files.

typedef struct sfp_info_s {
        int port;
        char platform_id[50];
        sff_eeprom_t sff_type; 
        char status_str[50];
        sff_dom_t sff_dom; 
}sfp_info_t;

sff_eeprom_t is defined in a header file named : sff_db.h and this file itself includes other files :

#ifndef __SFF_SFF_H__
#define __SFF_SFF_H__

#include <sff/sff_config.h>
#include <AIM/aim_pvs.h>

#include <dependmodules.x>

What is the best way to create this API without the mess of including all these files in all the processes which need to know only the structure of the message?

manish ma
  • 1,706
  • 1
  • 14
  • 19
  • Can't you just add `#include ` to the top of the header file for your API? Why is this a problem? (Or were you perhaps looking for some way of implementing [opaque types in C](https://stackoverflow.com/q/2301454/1679849)?) – r3mainer Jan 25 '18 at 11:09
  • Once I include this header file a lot of other irrelevant and unneeded information will also be included. For example, aim_pvs.h will provide functions and structs I have no use of in other processes. – manish ma Jan 25 '18 at 11:24

1 Answers1

2

The C standard allows a pointer to a struct to be converted to a pointer to its first member and back. So you can package the members you want to expose into a struct and publish that in a public header:

typedef struct
{
    int port;
    char platform_id[50];
} sfp_public_t;

In a private header, you would have:

typedef struct
{
    sfp_public_t public;
    sff_eeprom_t sff_type; 
    char status_str[50];
    sff_dom_t sff_dom; 
} sfp_info_t;

Given a pointer p to an sfp_info_t, you may convert it to a pointer to an sfp_public_t and pass it to other code. When you receive such a pointer from other code, you may convert it to a pointer to an sfp_info_t.

The other code will of course not know the true size of the object, so it cannot allocate new instances. Your API will need to provide supporting routines to allocate such objects.

A drawback is this requires you access the packaged members using p->public.name instead of p->name inside your code, although the code that receives the converted pointer can simply use p->name. I think you may be able to avoid that by using an anonymous struct member inside sfp_info_t. But an anonymous struct cannot be declared with a tag or a typename, so you need to repeat the declaration:

typedef struct
{
    struct
    {
        int port;
        char platform_id[50];
    };
    sff_eeprom_t sff_type; 
    char status_str[50];
    sff_dom_t sff_dom; 
} sfp_info_t;
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312