foward typedef structures - c

gcc 4.4.4 c89
I have this in my header file.
port.h
struct struct_tag;
int initialize_ports(struct_tag *port);
In my implemenation file I have this:
port.c
typedef struct struct_tag {
int port_id;
} Port_t;
And in my driver.h file, I have the following:
#include "port.h"
int initialize_ports(struct_tag *port)
{
port = malloc(sizeof *port);
/* do checking here */
}
I have forward declared the structure, as I want to hide the internal elements.
However, I am getting the following error on my initialize_ports in the header file:
expected ‘)’ before ‘*’ token
I am just wondering how can I forward declare and be able to pass the structure as a parameter?
Many thanks for any advice,

You should use:
int initialize_ports(struct struct_tag *port);
^^^^^^
Also, forward declarations give you an incomplete type which you don't know the size of. If you need to allocate a struct struct_tag you need to include the full definition for it. Alternatively you could use some create_struct_tag() function if you want to make it fully opaque.

As other answers have noted, you could change struct_tag to struct struct_tag in the prototype. Another way of getting your code to compile is to write
typedef struct struct_tag struct_tag;
in place of your existing struct struct_tag; (i.e. combine the typedef with the forward definition). That then does allow you to write
int initialize_ports(struct_tag *port)
without compile failures. However, this is still not quite what you want, because the caller can neither allocate a local variable of this type, nor malloc() one - because they don't know the size.
Other answers have suggested that you should open up the definition of the structure. That's generally not the right answer - because it removes the abstraction layer you're trying to create. Much better to have functions (in the port.c, i.e. the library that does know about the internals) such as:
struct_tag *create_port(...);
void free_port(struct_tag *port)
i.e. to create and free the structures - and indeed for other operations (such as reading from / writing to the structure) too.

You'll get an error as you don't KNOW the size of "port" as all it has to go on is the forward declaration.
In summary you are best off not using a forward declaration here unless you also set a constant value that is the sizeof "struct_tag" ... You would most likely be best off just fully declaring it.

The sizeof operator is evaluated at compile time not runtime, so at the line:
port = malloc(sizeof *port);
the compiler has no information regarding the size of the structure.
Solutions include:
fully define the type in the header file.
define initialize_ports() in port.c after the struct is fully defined.
have initialize_ports() call a function defined in ports.c to get the size of Port_t at run-time.
In any case you should not define initialize_ports() in the header file driver.h unless your compiler supports the inline or _inline keyword and you use it. Such usage would however render the code non ISO C compliant, and therefore less portable, however due to C++'s standard support for the keyword, you are likely to find it as an extension in most C tool-chains that include C++ compilation, so long as you do not use excessively strict compliance options.
However the error message you are getting is for a different reason. Unlike C++ in C struct_tag alone does not represent a type (if it did, you'd not have needed the typedef!), you must use the struct keyword.

Related

Is there a way to make a struct definition "private" to a single translation unit in C?

In C, you can use the static keyword to make global variables and functions private to the file in which they're defined. The compiler won't export these symbols, and thus the linker will not allow other modules to use these definitions.
However, I'm struggling to figure out how to restrict a struct definition such that it doesn't get added as an exported symbol that could accidentally be used by another module during the linking process. I would like to restrict this to the only file in which its defined.
Here are my attempts thus far which I've been struggling with.
// structure that is visible to other modules
struct PrivateStruct
{
int hello;
int there;
};
// this seems to throw an error
static struct PrivateStruct
{
int hello;
int there;
};
// i would ideally like to also wrap in the struct in a typedef, but this definitely doesn't work.
typedef static struct PrivateStruct
{
int hello;
int there;
} PrivateStruct;
Edit: I realize if I just define this struct in the .c file, others won't know about it. But won't it still technically be an exported symbol by the compiler? It would be nice to prevent this behavior.
I realize if I just define this struct in the .c file, others won't know about it. But won't it still technically be an exported symbol by the compiler?
No. Whether you are talking about structure tags or typedefed identifiers, these have no linkage. Always. There is no sense in which it would be reasonable to say that they are exported symbols.
This is among the reasons that header files are used in C. If you want to use a structure type in one compilation unit that is compatible with a structure type in a different compilation unit then compatible structure type declarations must appear in both. Putting the definition in a header makes it pretty easy to achieve that.
yes..... you can use pointers to the structure, and to the outer world it is not deferrable. Normally, that requires two header files, the first is the public one:
header mystruct.h
This header is public, used by client code.
struct my_opaque;
/* we cannot use *p fields below, as the struct my_opaque is
* incompletely defined here. */
void function_using(struct my_opaque *p, ...);
header mystructP.h
This header is private, and includes the public header file to maintain the
API to the client code.
#include "mystruct.h" /* safety include (1) */
struct my_opaque {
/* ... */
};
implementation mystruct.c
In implementation code, we include the private header file, and so, we have full access to the structure fields.
#include "mystructP.h"
/* we have full definition, as we included mystructP.h */
void function_using(struct my_opaque *p,
...)
{
... /* we can use p->fields here */
}
(1) the safety #include allows to change the struct my_opaque and the API functions, and the compiler to blame you if you change something in the api to the caller modules, forcing you to recompile if you change something in that API.

What is strong typing in c?

I have read this code snippet somewhere but i am not able to understand it's meaning.
/** Use strong typing for ODP types */
#define odp_handle_t struct {} *
What is significance of above code snippet?
This code snippet defines the symbol odp_handle_t which represents an opaque handle to a resource. It's opaque because it's a pointer to an empty struct. The thing that it's pointing to is not exposed to the user. It's called a handle because it does not point directly to the resource, it just identifies it. The internal implementation knows how to use this handle to access the required resource. This helps maintain independence between the client code and the implementation of the API. Finally, the strong typing part comes from the fact that it's a pointer to a type (the empty struct) as opposed to a void pointer.
That is just some nonsense code not really related to strong typing. It appears to be some non-standard way of declaring a pointer to incomplete type, but it is not valid C.
#define odp_handle_t struct {} *
odp_handle_t x; // will not compile, struct has no members
I believe this is yet another pointless gcc extension. Also, hiding away pointers behind typedefs is always a very bad idea.
There is no reason why you can't declare your pointer to incomplete/opaque type with pure standard C, and you can do so without hiding pointers behind typedefs:
h file
typedef struct odp_handle_t odp_handle_t;
c file
struct odp_handle_t
{
// have to put struct members in here
};
caller c file
odp_handle_t *pointer_to_incomplete_type;

How to export/import a C struct from a DLL/ to a console application using __declspec( dllexport/import )

This is my first time dealing with DLLs. Following the MSDN documentation I created a header file fooExports.h with macros defined according to a preprocessor definition:
#ifdef FOODLL_EXPORTS
#define FOO_API __declspec( dllexport )
#else
#define FOO_API __declspec( dllimport )
My intention was to use this header both in my DLL implementation as well as in the console application. So far importing and exporting functions works just fine. The problem arrises when I try to export an already defined struct that I need as parameter for one of the exported functions. For example, in the aforementioned header file I declare FOO_API void foo( FooParams *args ) and args is a struct defined as follows:
typedef struct FooParams
{
char *a;
char *b;
void *whatever; //some other type
} FooParams;
This struct has to be defined in foo.h rather than in fooExports.h. Is there any way to export this struct without taking it out of it's original header file (taking into consideration that I want to keep the exports/imports centralized in fooExports.h).
What would be a better approach to doing this? The DLL is all C as well as the client application using it.
If the only use the client will ever have for FooParams is to get pointers to it returned from DLL functions and to pass those pointers to other DLL functions, you can make it an "opaque type": Put
typedef struct FooParams FooParams;
in fooExports.h. The FOO_API macro does not belong on that declaration. An opaque type means the client code cannot:
Create any variables of type FooParams (but FooParams * ptr = NULL; is okay).
Do anything at all with any member of FooParams.
Find sizeof(FooParams) - and therefore cannot correctly malloc space for one or more FooParams objects.
You can't #define macros visible to the client which do any of the above, either. So your DLL would need to have one or more "constructor" or "factory" functions, maybe something like
FOO_API FooParams* CreateFooParams(const char * input);
It's also good practice to define a matching "destructor" function like
FOO_API void DestroyFooParams(FooParams * p);
even if the definition is as simple as { free(p); }, because there can sometimes be issues if memory allocated inside a DLL is freed by code outside it or vice versa (because not all Windows code uses identical definitions of malloc and free).
If all this is too extreme, the only other option is to put or #include the struct definition in the exported header file and make it visible to clients. Without that, any attempt to do something to a FooParams, other than passing pointers around, is going to be impossible because the compiler won't know what's in a FooParams. The compiler (as opposed to the linker) takes information only from commandline arguments and #include-d files, not from libraries or DLLs.

Why making an empty struct a new typedef and using it as a pointer type?

I have a header and a sample application using this header, all in C, I get almost all the logic of this software except for this; this the interesting part of the header:
struct A;
typedef struct A A;
in the C application this A is only used when declaring a pointer like this
A* aName;
I'm quite sure that this is a solution for just including A in the scope/namespace and give just a name to a basically void pointer, because this kind of pointer is only used to handle some kind of data, it is more like some namespace sugar.
What this could be for?
You're correct that it's like a void pointer, in that void is an incomplete type, and in this file A is also an incomplete type. About all you can do with incomplete types is pass around pointers to them.
It has one advantage over void* in this file, that it's a different and incompatible type from some other bit of code that has done the same thing with B. So you get a bit of type safety. If A is windowHandle and B is jpgHandle, then you can't pass the wrong one to a function.
It has an advantage over void* in the .c file that defines the functions that accept an A* -- that file can contain a definition of struct A, and give A whatever members it wants, that the first file doesn't need to know about.
However, you say there are no other mentions of A in any header file, which means there are no functions that accept or return it. You also say that the only use of A in your source file is to declare pointers -- I wonder where the values of those pointers come from, if any.
If all that happens if that someone defines an uninitialized A* and never uses it, then clearly this is a remnant of some old code, or the start of some code that never got written, and it shouldn't be in the file at all.
Finally, if the real type is called something a bit less stupid than A, then the name might give a clue to its use.
I assume struct A is a forward declaration. It most likely is defined in one of the .c-files.
Doing so struct A's members are private to the module defining it.
This is an example of an opaque pointer, which is useful for passing handles. See http://en.wikipedia.org/wiki/Opaque_pointer for some further info. What may be interesting here from a C++ perspective, is the notion that you can define a class with a member that is a pointer to an (as yet) undefined struct. Although this struct is thus not yet defined in the header, in some later cpp implementation this struct is given body, and the compiler does the rest. This strategy is also called the Pimpl idiom (more of which you will find LOTS on the internet). Microsoft discusses it briefly at http://msdn.microsoft.com/en-us/library/hh438477.aspx.

Expected symbol problems with this function declaration

I am just getting back into the C programming realm and I am having an issue that I think is linker related.
I am using cmake for the first time as well, so that could be adding to my frustration.
I have included a third party header file that contains a typedef that my code is trying to use, and it has this line:
typedef struct pcap pcap_t;
so my code has
pcap_t *var;
//later.....
var->fd;// this line throws the error
which throws the
error: dereferencing pointer to incomplete type
So am I just missing another include file, or is this a linker issue? I am building this code in QtCreator and using cmake. I can dive on a_t to see that typedef declaration in the included header, but I can't seem to dive on "struct a" itself to see where it's coming from.
Thanks
edited the code above to reflect that I am using the pcap libraries
so i have included in my source file's header file the following lines
#include <net/bpf.h>
#include <pcap/pcap.h>
so I guess between these two includes, I am missing the defintion of the pcap structure. Where can I find it?
Thanks
The typedef statement does two things. It declares the existence of something of type struct a. It also declares that a_t is an alias for struct a. Declaring the existence of a type without any information to determine its size is called by the C language an incomplete type. The declaration is colloquially referred to as a forward declaration, and the type is colloquially referred to as opaque to those parts of the code that never get to see the type's definition.
typedef struct a a_t;
a_t *var;
The C language allows pointers to an incomplete type to be defined. A pointer to an incomplete type is not itself incomplete, since a pointer to a type is the same size as a void pointer. But, your code then attempts to dereference the pointer:
var->member;
Since there is no definition of struct a available, the compiler has caught an error in your program, and is telling you about it. It is not a linker issue, but a semantic error in your program.
An opaque type is a way to hide implementation details from the user of the type. That is, it is C's way of providing an interface:
typedef struct a a_t;
a_t *a_create ();
void a_destroy (a_t *);
int a_get_member (a_t *);
void a_set_member(a_t *, int);
Then, in your code, you are expected to use the interface.
a_t *var = a_create();
a_set_member(var, 10);
int m = a_get_member(var);
a_destroy(var);
The source file that implements the interface would actually define what struct a looks like. Since you said you had no definition to reference in your debugger, this likely means you did not provide a definition anywhere in your program.
Edit: It seems you are trying to use the packet capture library. You will need to include the <pcap.h> header file to your code, and link with -lpcap. If the header file or library does not exist, you will need to install the packet capture development package for your OS. The <pcap.h> has made a typedef for pcap_t already, and it is intentionally opaque. So you will have to use the interfaces the header file defines to access the information you want.

Resources