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?
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;
Related
I find a foo.h file having:
typedef STRUCT_s STRUCT;
STRUCT *foo();
and the foo.c file:
#include "i_foo.h"
struct STRUCT_s{
//...
};
#define STRUCT struct STRUCT_s
STRUCT *foo()
{
STRUCT *s;
//...
return s;
}
Is it the common way to hide the structure definition in C ? If yes, I wonder, if the structure is not declared in the header, how is the client supposed to use it?
This is a common way to hide structure definition in C. And client isn't supposed to use structure directly. He has to use only proposed functions from interface to interact with data: instantiate, set or get values, launch operation on it,....
With this way, implementation is totally hidden to client. So client is not constraint by changes in implementation. Library can evolves as it need without disturbing client, according no change in interface.
The user this way cannot instantiate a structure and only sees objects of this type as pointers. Therefore all the constructors and methods, getters, setters etc. are obscure to the user and should be defined in the library source.
One obvious additional consequence is that if you change the structure, the user does not have to change all its uses in the code to initialize new fields or comment out the uses of defunct ones. Since there were none, and there won't be any. The struct's internal private structure is totally hidden.
Yes, this is the common way to declare an abstract data type (ATD). An ADT is used only through its interface which is represented by the functions declared in the header file. A client doesn't access the fields directly. It's also a good idea to add a prefix to all exported identifiers. This avoids name clashes and makes it clear where an imported identifier comes from.
Example:
Stacks.h
typedef struct Stacks_StackDesc *Stacks_Stack;
Stack Stacks_New(void);
void Stacks_Push(int x, Stacks_Stack s);
void Stacks_Pop(Stacks_Stack s, int *top);
Stacks.c
#include "Stacks.h"
struct Stacks_StackDesc {
...
};
Stack Stacks_New(void)
{
...
}
void Stacks_Push(int x, Stacks_Stack s)
{
...
}
void Stacks_Pop(Stacks_Stack s, int *top)
{
...
}
this error seems very easy to fix but i've been trying and have no clue.
So i have three files:
symtable.h:
typedef struct symbolTable *SymTable_T;
symtablelist.c:
#include "symtable.h"
struct Node{
char* key;
void* value;
struct Node* next;
};
struct symbolTable{
struct Node* head;
int length;
};
SymTable_T SymTable_new(void){
/* code */
}
And main.c:
#include "symtable.h"
int main(int argc, const char * argv[]) {
// insert code here...
SymTable_T emptyTable = SymTable_new();
emptyTable->length = 3; <------- ERROR
return 0;
}
I'm getting error: Incomplete definition of type "struct symbolTable"
Can anyone please give me a hint?
The reason i declare my struct in my source file is that i will have another implementation for the header file. so is there another way to fix my bug beside moving my struct declaration?
You can't access the members directly with an opaque pointer - if you keep the implementation in a separate source file, you'll have to access all the members via your interface, and not directly mess with the struct.
For instance, add this to symtable.h:
void SymTable_set_length(SymTable_T table, int len);
this to symtablelist.c:
void SymTable_set_length(SymTable_T table, int len)
{
table->length = len;
}
and in main.c change this:
emptyTable->length = 3;
to this:
SymTable_set_length(emptyTable, 3);
although in this specific case passing the length as an argument to SymTable_new() is an obviously superior solution. Even more superior is not letting the user set the length of a linked list data structure at all - the length is the number of items in it, and it is what it is. It would make no sense to, for instance, add three items to the list, and then allow main.c to set the length to 2. symtablelist.c can calculate and store the length privately, and main.c can find out what the length is, but it doesn't make much sense for main.c to be able to set the length directly. Indeed, the whole point of hiding the members of a struct behind an opaque pointer like this is precisely to prevent client code from being able to mess with the data like that and breaking the data structure's invariants in this manner.
If you want to access the members directly in main.c, then you have to have the struct definition visible, there is no alternative. This will mean either putting the struct definition in the header file (recommended) or duplicating it in main.c (highly unrecommended).
In typedef symbolTable *SymTable_T;, you refer to a non-existent type symbolTable. In C (unlike C++) the type is named struct symbolTable. (Note: the question has changed to fix this since answering it.)
There's a second problem. In main.c the code will need to be able to see the definition of struct symbolTable for you to be able to refer to fields of emptyTable. At the moment, the definition is hidden in a .c file... it should be moved to the header.
I'm working on a library for a user to use and manage with the function prototypes I provide within my header file. Now I have a working hashtable setup in manager.c but I'm at a loss at how to tackle this. I basically want to keep the hashtable "under the hood" from the user by providing them with
typedef struct Manager {
int size;
HashList **table;
} Manager;
so they can create this Manager object and use my provided functions to manipulate its contents. However, HashList is declared in my manager.c as
typedef struct HashList {
/*
* data stored here
*/
struct HashList *next;
} HashList;
Now obviously this will not compile as HashList must be in my header file since struct Manager uses HashList. But I do not want HashList to be in the header file as the user shouldn't explicitly have access to this as my functions manipulate the data stored at each hash.
Any advice?
If the user writes: Manager *m = ...;, is it expected that they'll ever write m->xyz? If not, then you don't need to expose the internals to the end user at all — it is sufficient to provide them with:
typedef struct Manager Manager;
If they must dereference the Manager type, it suffices to define:
typedef struct HashList HashList;
in the public header. They don't need to access the insides of that. (Well, if you've any pretensions to providing a concealed service, they have no need for that.)
Between the two options, option 1 is preferable. You provide functions that create and destroy the Manager type, and that allow the user to get or set the size of the structure. With the FILE * type, you don't write code that pokes inside the structure; you just use it via the interface functions you define. You should enforce the same discipline on the users of your code.
Note that if you allow the user to poke at the size element in the Manager structure, you can never tell when they changed it, so you've no idea whether your structure has been corrupted. If you have functional access to it (a get and a set function), you control what happens when the size changes.
You need to make your struct opaque. Keep the implementation details in the library .c files or a private header file and only provide a typedef only.
Example:
library.c
struct SomeStruct
{
int value;
};
struct SomeStruct *some_struct_alloc()
{
return malloc(sizeof(SomeStruct)));
}
void some_struct_set_value(struct SomeStruct *someStruct, int value)
{
if (someStruct != NULL)
someStruct->value = value;
}
int some_struct_value(struct SomeStruct *someStruct)
{
if (someStruct != NULL)
return someStruct->value;
return SOME_INVALID_VALUE_PERHAPS;
}
library.h
typedef struct SomeStruct SomeStruct;
SomeStruct *some_struct_alloc();
void some_struct_set_value(SomeStruct *someStruct, int value);
int some_struct_value(SomeStruct *someStruct);
program.c
#include <library.h>
int main()
{
SomeStruct *someStruct;
someStruct = some_struct_alloc();
if (someStruct == NULL)
return -1;
some_struct_set_value(someStruct, 3);
printf("%s\n", some_struct_value(someStruct));
free(someStruct);
return 0;
}
If the user tries to dereference the someStruct in main() then the compiler would halt with an error similar to dereferencing pointer of incomplete type.
In my opinion, this is a very good way to protect your library's data structure from being misused.
In my library, I have an instance structure, which contains everything needed for the library, this is so you can define multiple instances of the library. The library requires the user to define their own extension, or custom variables.
This is what I tried:
Library.h
typedef struct custom_s *custom;
typedef struct {
int a;
int b;
custom customs;
} instance;
And then the user can just do:
Main.c
// User sets their own custom structure
struct custom_s {
int c;
};
int main(void) {
instance test;
test.customs.c = 1;
}
However I get the error of "Segmentation fault".
Shouldn't it be:
test.customs->c = 1
Since you type'd it in
typedef struct custom_s *custom;
and Used as
custom in the instance structure.
Which is never allocated...
typedef struct custom_s *custom;
Defines a pointer to a custom struct. In your example this is an undefined pointer that is never allocated, so a segmentation fault occurs when you try to access it.
One side effect of opaque structures is that the size is unknown to client code. This means that you must create your own functions for allocating/creating them.
Make something like:
instance test;
test.customs = customs_create();
test.customs.c = 1;
I use the following code a lot in C:
typedef struct
{
int member;
} structname;
Now i'm trying to keep that struct definition local to a particular source file, so that no other source file even knows the struct exists. I tried the following:
static typedef struct
{
int member;
} structname;
but GCC whines because of an illegal access specifier. Is it even possible to keep a struct's declaration private to a source file?
If you declare the typedef struct within a .c file, it will be private for that source file.
If you declare this typedef in a .h file, it will be accesible for all the .c files that include this header file.
Your statement:
static typedef struct
Is clearly illegal since you are neither declaring a variable nor defining a new type.
All declarations are always local to a particular translation unit in C. That's why you need to include headers in all source files that intend to use a given declaration.
If you want to restrict the use of your struct, either declare it in the file in which you use it, or create a special header that only your file includes.
A structure definition is private to a source file unless placed in a shared header file. No other source file can access the members of the struct, even if given a pointer to the struct (since the layout is not known in the other compilation unit).
If the struct needs to be used elsewhere, it must be used only as a pointer. Put a forward declaration of the form struct structname; typedef struct structname structname; in the headerfile, and use structname * everywhere else in your codebase. Then, since the structure members appear only in one source file, the structure's contents are effectively 'private' to that file.
Hernan Velasquez's answer is the correct answer: there are several problems with your code snippet. Here's a counter-example:
/* This should go in a .h if you will use this typedef in multiple .c files */
typedef struct {
int a;
char b[8];
} mystructdef;
int
main (int argc, char *argv[])
{
/* "static" is legal when you define the variable ...
... but *not* when you declare the typedef */
static mystructdef ms;