Typedefs for available/unavailable types - c

I have a C module foo.c which defines a function
json_t* foo_to_json(foo_t*);
The user of this code may or may not have the Jannson library available, I check that with autoconf, feed the value in by config.h and include the Jannson header conditionally.
#ifdef HAVE_JANNSON_H
#include <jannson.h>
#endif
I use this function in a few places, and rather than #ifdef around every call, I find it convenient to have a "fail version" in place
#ifdef HAVE_JANNSON_H
json_t* foo_to_json(foo_t *foo)
{
<create and return a json_t>
}
#else
json_t* foo_to_json(foo_t *foo)
{
fprintf(stderr, "no JSON support\n");
return NULL;
}
#endif
Problem: json_t is not defined if jannson.h is not included. I know that in that header, it is defined as
typedef struct json_t { <details> } json_t;
and I find that including the partial
typedef struct json_t json_t;
in my code [edit: in my code's header] allows it to compile with gcc 10 -Wall -Wextra, with or without the jannson.h header. I know that you shouldn't "double typedef" prior to C11, and I'd like to support earlier C versions. Is there a way?
Possible methods:
use struct json_t* everywhere instead of the typedefed json_t, that does seem to work, but is a bit ugly ...
use void* everywhere, rely on casting to json_t*, again, seems to work, but even uglier.
Is there an elegant solution?
Edit: In response to comments, the partial typedef that I'm using is in the header which exports foo_to_json and is installed, so making that typedef conditional on HAVE_JANNSON_H would mean exporting/installing that too, and I'd like to avoid that. I have considered making a foo-config.h.in from which configure generates the partial conditionally (but which can be installed without config.h).

Related

C function implementations in header files

I am implementing some data structures in C, with the goal of being able to use them easily for future projects.
One possible way to do this is to implement each of the data structures in a header file.
For example, here is linked_list.h:
#ifndef LINKED_LIST
#define LINKED_LIST
#include <stdlib.h>
typedef struct linked_list_type {
int val;
struct linked_list_type* next;
} linked_list;
// Initializes a single node with a value v
linked_list* ll__init(int v) {
linked_list* new_ll = malloc(sizeof(linked_list));
new_ll->val = v;
new_ll->next = NULL;
return new_ll;
}
// More functions
#endif
This works nicely, since I can just use #include "linked_list.h" to get the linked_list struct and all its functions in a future project.
However, it goes against the normal practice of just using declarations (and not implementations) in a header file. So, I have some questions:
Is there a better way to get easy inclusions like this? From some searching, it seems that including a .c file is a bad idea.
Is what I'm doing right now bad/dangerous in a way that I don't realize?
Re your first question, the standard way is to just to link the code, either in the form of another .c file or in a static library. But you could also use inline for everything. (I don't consider this a good solution for larger data structures though.)
Re your second question, one danger is that you will get a linker error if you try to link together two (or more) compiled files that have been separately compiled using this header file. The ll_init symbol will be defined by each .o file.
You reminded my about blaze math library. It is quite fast math library which uses only headers. So, yeah. You can put all implementations in headers with lots of inline. But compilation will be a bit slower. As I remember, godbolt online compiler often timeouted for me with blaze.

Makefile with unimplemented functions in library

First of all, I've been searching for an answer here and I haven't been able to find one. If this question is really replicated please redirect me to the right answer and I'll delete it right away. My problem is that I'm making a C library that has a few unimplemented functions in the .h file, that will need to be implemented in the main.c that calls this library. However, there is an implemented function in the library that calls them. I have a makefile for this library that gives me "undefined reference to" every function that's not implemented, so the when I try to link the .o s in the main.c file that does have those implementations I can't, because the original library wasn't able to compile because of these errors.
My question is, are there any flags that I could put in the makefile so that it will ignore the unimplemented headers or look for them once the library is linked?
This is a very old-fashioned way of writing a library (but I've worked on code written like that). It does not work well with shared libraries, as you are now discovering.
If you can change the library design
Your best bet is to rearrange the code so that the 'missing functions' are specified as callbacks in some initialization function. For example, you might currently have a header a bit like:
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
extern int implemented_function(int);
extern int missing_function(int);
#endif
I'm assuming that your library contains implemented_function() but one of the functions in the library makes a call to missing_function(), which the user's application should provide.
You should consider restructuring your library along the lines of:
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
typedef int (*IntegerFunction)(int);
extern int implemented_function(int);
extern IntegerFunction set_callback(IntegerFunction);
#endif
Your library code would have:
#include "header.h"
static IntegerFunction callback = 0;
IntegerFunction set_callback(IntegerFunction new_callback)
{
IntegerFunction old_callback = callback;
callback = new_callback;
return old_callback;
}
static int internal_function(int x)
{
if (callback == 0)
...major error...callback not set yet...
return (*callback)(x);
}
(or you can use return callback(x); instead; I use the old school notation for clarity.) Your application would then contain:
#include "header.h"
static int missing_function(int x);
int some_function(int y)
{
set_callback(missing_function);
return implemented_function(y);
}
An alternative to using a function like set_callback() is to pass the missing_function as a pointer to any function that ends up calling it. Whether that's reasonable depends on how widely used the missing function is.
If you can't change the library design
If that is simply not feasible, then you are going to have to find the platform-specific options to the code that builds shared libraries so that the missing references do not cause build errors. The details vary widely between platforms; what works on Linux won't work on AIX and vice versa. So you will need to clarify your question to specify where you need the solution to work.

Howto handle typedefs without include headers in headers

As for working on a larger project, I want to throw in some own types (e.g. myType). The "rushing in"-approach would be, to put those typedefs into an header (lets say myType.h), together with a bunch of functions working on those types.
If I use the new type somewhere, I include myType.h to my source-file. Fine.
But if I want to use the new type somewhere as an argument in a function-signature, I need to include the myType.h to the header of the module containing the function. With one or another typedef, this seems to be okay for me, but the more types I have, the more includes in headers I need, possible including further header, while using type including other own types. This is resulting in what I call "dependency hell".
Is there a clever, stylish, best practice, what-so-ever way to solve this dilemma?
I'm aware of the possibility to pass those types as void-pointer, casting them back inside the function, but then I loose important type-checking from the compiler.
Furher, extern is considered worst-practice around here..
EDIT:
In detail:
myType.h:
#include "otherType.h"
typedef struct {
char Name[32];
int Size;
otherType someType;
} myType;
processSomeHow(myType _myType, int NewSize);
otherType.h
#define SOME_CONST 32
typedef struct { [...] } otherType;
someModule.h:
#include "myType.h"
int specialProcessSomeHow(myType _myType);
someModule.c:
int specialProcessSomeHow(myType _myType)
{
int Size = 64;
return(processSomeHow(_myType, Size));
}
Now I include otherType.h indirectly to someModule.h, even worse, I include it to every module, that includes someModule.h. Now I have a SOME_CONST everywhere and it's hard to figure out, from where it comes. I have to maintain two include trees.
like in the gtk library you can use one headfile and split it on your needs.
type.h
- myType.h
-- someType.h
- otherType.h
- List item
and on your CONST-Problem:
If you just need it for one c.file. Don't use them in HeaderFile.
And you could name them like "MY_TYPE_SOME_CONST" or "OTHER_TYPE_SOME_CONST";
//EDIT:
to make it clear: just add 'this.h' file and name it.
#ifndef TYPE_H_
#define TYPE_H_
#include myType.h
#include someType.h
#include otherType.h
#endif /* TYPE_H_ */
now you can use "#include this.h" for each file you need your types.
(this.h is not real, name it to something unique)
You can (and probably should) use forward declarations for your custom types. See details here: typedef stuct with forward declaration in C
Your interfaces (the headers) should have incomplete types (i.e. pointers to your custom types) and inside the source code (c files) you should include the My_Type.h.
You're worrying unnecessarily : There is no 'dependency hell', precisely because you are giving the compiler all the information it needs to do it's job.
Here's my rules for this:
Always, always use header guards.
Every .h file should
explicitly #include every other .h file it needs in order to compile,
and no more.
So if b.h uses a type from a.h, then b.h must #include "a.h". If b.c uses functions from a.h, but b.g doesn't use types from it, then b.c should #include a.h.
There's no need for extern keyword on functions in .h files, because IIRC modern compilers deduce this correctly.
Using extern for global variables may well be frowned on, with good
reason.
Cluttering of global namespace. C++ namespaces address this, but in C you have to use naming conventions for all global types, functions and #defines. Pick a convention that works for you : I've seen teams successfully use a LETTER-DIGIT-DIGIT prefix for every source file, so foo.h might become (for example) B04_foo.h, and all functions/types get the same B04_ prefix. It's a bit crude, but it works. As I say, pick one that works for you.

Solving a circular dependency - C

I checked SO for duplicates of this, but was unable to find an exact solution for my problem.
I have a header file NvCommon.h where I use an enum NV_DATA_TYPE. This enum is defined in another header NvDefs.h where I use a number of structs and enums from NvCommon.h. I can't build this due to circular dependency. I know that forwrd declaring enum is not possible.
In this situation what could be done? Is this a problem with my design? Do I have to introduce another header file to solve this?
I am no C expert. Please help me. My design may have issues and I know can fix this circular dependency by introducing another header file. What I would like to know is "is that the only way around". Looking for alternate solutions if available.
I will post the full code if it is helpful.
It can be useful to define enums in their own file(s), and if you do that here, your problem will disappear.
If I understand your question correctly, you've got something like this:
derpfoo.h:
#ifndef DERPFOO_H
#define DERPFOO_H
#include "derpbar.h"
typedef struct {
char *nothing;
} FOO;
BAR foo (BAR derp) {
return derp;
}
#endif
derpbar.h:
#ifndef DERPBAR_H
#define DERPBAR_H
#include "derpfoo.h"
typedef struct {
char *nothing;
} BAR;
FOO bar (FOO derp) {
return derp;
}
#endif
and then a simple derp.c:
#include "derpfoo.h"
#include "derpbar.h"
int main (void) {
return 0;
}
A friend of mine presented me with this problem in some SDL code a while ago, and it took me a while to understand both why he was doing what he was doing and how to fix it reasonably.
The intention of separating the code like this is that derpfoo and derpbar are logically separate, but they are also, sadly, mutually dependent. The simplest solution I've found to such a thing is to combine them and split them according to anatomy rather than logic like so:
derpstructs.h:
#ifndef DERPSTRUCTS_H
#define DERPSTRUCTS_H
typedef struct {
char *nothing;
} FOO;
typedef struct {
char *nothing;
} BAR;
#include "derpfunctions.h"
#endif
derpfunctions.h:
#ifndef DERPFUNCTIONS_H
#define DERPFUNCTIONS_H
#include "derpstructs.h"
BAR foo (BAR derp) {
return derp;
}
FOO bar (FOO derp) {
return derp;
}
#endif
and still a simple derp.c:
#include "derpstructs.h"
#include "derpfunctions.h"
int main (void) {
return 0;
}
Note that derpstructs.h includes derpfunctions.h at the end rather than at the beginning. This is not, strictly speaking, necessary, but if you do intend to have them include each other, you must include the function definitions after the struct definitions that they depend on, in all possible inclusion paths. Moving on...
This solution works, but it's not exactly sticking with the original philosophy that caused the problem to begin with -- that the two parts are logically separate, and should be kept so in the code.
The answer to both is to split everything up further, and tweak the inclusion paths even more.
derpfoostructs.h includes derpbarstructs.h first and then defines struct FOO and then at the end optionally includes derpfoofunctions.h and derpbarfunctions.h.
derpbarstructs.h includes derpfoostructs.h first and then defines struct BAR and then at the end optionally includes derpfoofunctions.h and derpbarfunctions.h.
derpfoofunctions.h includes derpfoostructs.h and derpbarstructs.h first, then includes derpbarfunctions.h, and then defines its functions.
derpbarfunctions.h includes derpfoostructs.h and derpbarstructs.h first, then includes derpfoofunctions.h, and then defines its functions.
derp.c includes derpfoostructs.h and derpbarstructs.h and then includes derpfoofunctions.h and derpbarfunctions.h, and then goes on to do whatever else it needs to do.
This satisfies both of the desired requirements. It eliminates circular dependencies, and still maintains logical separation of the two logically separate code units. You get two files to edit when you change from project to project instead of one, but it at least keeps the mutable code apart from the immutable. That, and it's the only solution I've found.
Hope this helped. Good luck on your projects.
Circular dependencies might mean that you're overdesigning your interface. Merge both files into Nv.h. If this trivially solves the problem, this means you were incorrectly designing the interface.
Check this out
How to properly declare and define variables, libraries, functions , etc. This might be relevant.
I tried modeling this problem based on your description. In my implementation, I tested three things (1) declaring but not defining NV_DATA_TYPE in NvDefs.h, (2) declaring and defining NV_DATA_TYPE in NvDefs.h, and (3) defining NV_DATA_TYPE in NvDefs.h, but declaring it NvCommon.h. Also, as your description provided, I created some structs in NvCommon.h and accessed those objects in NvDefs.h. In every case--with and without guards in the header files--the code compiled and executed with correct results.
Is it possible that your circular dependency is somewhere else in your header files besides the NV_DATA_TYPE enum?

Managing redundant typedefs from multiple vendors

What are some of the best ways to manage redundant typedefs used for platform independence from multiple middleware (operating systems, protocol stacks) vendors in the C programming language.
e.g.:
target.h
/* inclusion lock etc */
typedef char CHAR;
typedef unsigned char BYTE;
typedef unsigned short int WORD;
/* ... more of the same ... */
OS_types.h
/* inclusion lock etc */
typedef char CHAR;
typedef unsigned char BYTE;
typedef unsigned short int WORD;
/* ... more of the same ... */
At some point the compiler recognizes that it has two redundant typedef symbols and bails out with an error because this is simply not allowed by definition in C.
One possible way to do this without modifying the vendor's header would be to use the preprocessor with some header wrappers, e.g.
mytypes.h
#define BYTE VENDOR1_BYTE
#include <vendor1/types.h>
#undef BYTE
#define BYTE VENDOR2_BYTE
#include <vendor2/types.h>
#undef BYTE
typedef unsigned char BYTE;
This would result in the vendor's code generating different typedefs but hopefully mapped to the same actual type (unsigned char in the example). If the vendors are using different underlying types for the same type names then the method will likely not work.
That's a toughie. If I had to do something, I'd probably hold my nose and modify the third-party header-files -- possibly using macros to obtain conditional compilation of the offending typedefs.
Good luck.
If the vendor is responsive to feedback, you could beg them to move those generic type definitions into a separate file, e.g. types.h. If they're isolated in a separate file, it's much easier to manage. The solution could be as simple as removing their types.h and adding your own project-specific types.h which can do whatever it needs to do in your project.
Even better, beg them to use the standard C typedefs in stdint.h, i.e. uint16_t.
Otherwise, I'd suggest a modification to the vendor header files, done as cleanly as possible so it's easy to re-do when they next release code. Of course this all goes in your VCS so you can track exactly what changes you made!
One approach, although it could be a lot of work, is to build your own "wrapper" layers which provide only the functionality you need from each of the middleware vendors. If you keep each wrapper in its own compilation unit (.c file) that's the only place you'll need to refer to the vendor's header file. That gives you a way to prevent the conflicting types from "leaking" into your application, as you can use your own typedefs and translate them to the vendor-specific types in the wrapper.
As Steve suggested, modifying the header files might be the best solution, depending on how often the vendor ships new versions of their stuff. The overhead could get pretty high.
If you have the option to use C++ compilation for your own code (even if it is essentially C code) you could create namespace wrappers thus:
vendorA_target.h
namespace vendorA
{
extern "C"
{
#include <target.h>
}
}
vendorB_OS_types.h
namespace vendorB
{
extern "C"
{
#include <target.h>
}
}
Then in your own code. include these headers in place of the originals, and use scope-resolution, or if you are certain that types with the same name have identical or compatible definitions, simply us a using directive:
using vendorB::WORD
WORD timeout = 100 ;
vendorA::WORD x = 0xffff ;
Note that the extern "C" wrappers are not necessary if the headers already have them internally in __cplusplus macro conditionals - but it won't hurt.
Using C++ to compile C code imposes no overhead, but it does have stricter type comformaty checking, which while good for your code quality, may cause other headaches; especially if the third-party headers contain code that is invalid as C++. If the headers already have extern "C" declarations in __cplusplus macro conditionals, then they are already intended to be "C++-ready" and you may not have any such problems.
Unfortunately this method will not solve the problem of preprocessor macros with the same name. If you have that problem, you may have to #undef the macros from one header before including the other, or modify the headers.

Resources