Doxygen doesn't distinguish between `union myname` and `struct myname` - c

I've written a small matrix library as part of a larger project I am working on. It was important to have zero-cost transpositions, so I used/abused unions. The code itself works fine (provided below), but when it came to document with Doxygen, it combines all of the documentation for both struct matrix_r and union matrix_r into a single item. That is, there are only generated pages for struct matrix_r and struct matrix_c, but those two pages describe matrix_r and matrix_c as unions, with concatenated #brief text and concatenated attributes (from both the struct and union declarations).
I am very, very new to Doxygen, but I have been unable so far to figure out how to get it to treat these as separate documentation items. Any ideas?
#include <stddef.h>
/// #brief internal stuct for row-major matrices
struct matrix_r {
int *data; ///< raw pointer backing matrix
size_t m; ///< the number of rows
size_t n; ///< the number of cols
};
/// #brief internal struct for col-major matrices
struct matrix_c {
int *data; ///< raw pointer backing matrix
size_t n; ///< the number of cols
size_t m; ///< the number of rows
};
/// #brief user-facing typedef for row-major matrices
typedef union {
struct matrix_r id; ///< identity view of matrix
struct matrix_c tr; ///< transposed view of matrix
int* flat; ///< flattened view of matrix
} matrix_r;
/// #brief user-facing typedef for row-major matrices
typedef union {
struct matrix_c id; ///< identity view of matrix
struct matrix_r tr; ///< transposed view of matrix
int* flat; ///< flattened view of matrix
} matrix_c;

Structural commands start with a backslash (\), or (#) followed by a command name and one or more parameters. For instance, if you want to document the class Test , you could have put the following documentation block somewhere in the input that is read by doxygen:
/*! \class Test
\brief A test class.
A more detailed class description.
*/
Straight from the manual, here are some other commands:
Here the special command \class is used to indicate that the comment
block contains documentation for the class Test. Other structural
commands are:
\struct to document a C-struct.
\union to document a union.
\enum to document an enumeration type.
\fn to document a function.
\var to document a variable or typedef or enum value.
\def to document a #define.
\typedef to document a type definition.
\file to document a file.
\namespace to document a namespace.
\package to document a Java package.
\interface to document an IDL interface.
Edit:
I believe this is the way Doxygen is designed to work. See the
documentation here:
http://www.doxygen.nl/autolink.html
in the section "typedefs". It says:
Typedefs that involve classes, structs and unions, like
typedef struct StructName TypeName
create an alias for StructName, so links will be generated to
StructName, when either StructName itself or TypeName is encountered.
Doxygen considers the union tag name to be "the real thing",
not the typedef (which is considered like an alias of "the real
thing"). I'd recommend this:
/*!#brief The documentation of the union Name*/
typedef union Name
{
//.....
}Name;

Related

Doxygen: Documenting struct as a member of a struct

I would like to document a struct as a member of a struct, in a style, that there will be clickable link to structure precalculated same as on calibrator_calibration_t and after click it will show me all members of precalculated.
Generated HTML:
I've tried many different approaches but none of them worked as I needed. Any tip?
/**
* #struct filter_t
* #brief Filter structure
*/
typedef struct
{
calibrator_calibration_t calibration; ///< Copied calibration
blackbox_weight_id_e weight_id;
struct
{
float slope;
float above_mixed;
float under_mixed;
float above_male;
float under_male;
float above_female;
float under_female;
uint32_t stable_counter_minimum;
} precalculated; ///< Precalculated values (for faster calculation) based on settings
} filter_t;
If you want the type of structure member precalculated to be documented with a name and a link to separate documentation of that type, then you must give that type a name or tag. You have not done that. C does not allow you to name it (via typedef) when its definition is inside a struct definition, however, and it is poor style to tag it in that context.
If you can get over your apparent aversion to structure tags and are also unconcerned with the stylistic problems involved, then I anticipate that adding a tag would induce Doxygen to do what you want:
typedef struct
{
calibrator_calibration_t calibration; ///< Copied calibration
blackbox_weight_id_e weight_id;
struct precalc // Note the structure tag here
{
float slope;
float above_mixed;
float under_mixed;
float above_male;
float under_male;
float above_female;
float under_female;
uint32_t stable_counter_minimum;
} precalculated; ///< Precalculated values (for faster calculation) based on settings
} filter_t;
But if you are going to tag the structure type then it would be better form to move it out of the host structure definition, and if you're going to do that, then it appears that your standard convention would be to name it instead of tagging it:
typedef struct {
float slope;
float above_mixed;
float under_mixed;
float above_male;
float under_male;
float above_female;
float under_female;
uint32_t stable_counter_minimum;
} precalculated_t;
typedef struct
{
calibrator_calibration_t calibration; ///< Copied calibration
blackbox_weight_id_e weight_id;
precalculated_t precalculated; ///< Precalculated values (for faster calculation) based on settings
} filter_t;

more general definition of structs in C

I'm practicing C and it seems very tedious having to write algorithms for essentially the same data structures but that hold different data, especially since no namespace means I have to give extralong titles to everything
for example:
//double matrix
typedef struct DubMatrix DubMatrix;
struct DubMatrix {
int rows;
int cols;
double *data;
};
// int matrix
typedef struct IntMatrix IntMatrix;
struct IntMatrix {
int rows;
int cols;
int *data;
};
I have many functions that I would like to implement dealing with (among other things) matrices of different types of numbers, like algebraic numbers, elements of finite fields, etc.
I'm wondering if there is a way to avoid redoing essentially the same structs and functions over and over.
You could use tagged unions which are basically structures containing common data, and most importantly a tag field denoting the type, and a union for the data itself.
It could look like
struct Matrix
{
size_t rows;
size_t cols;
enum
{
INT,
DOUBLE
} type;
union
{
int *int_data;
double *double_data;
} data;
};
Then depending on the value of type you use either data.int_data or data.double_data.
Another possible solution is similar to the above, but instead of a union use a void * pointer for the data, and cast it as needed.
C does not really have the concept of generics or generic programming however there are a couple of tricks you can use.
You can use void pointers but they should be allocated big enough for the biggest thing you will store in them otherwise you will just access some place you are not supposed to.
Another thing you can use for generic-ish programming is unions which can have different variants consider following example which is one of standard oop polymorphism examples
struct triangle {...}
struct rectange {...}
union shape {struct triangle *;struct rectange *;}
enum type {triangle,rectangle}
struct shape {union shape *s,enum type type} /* this is like an interface*/
size_t area(struct shape *shape){...}
this looks tedious but could be easily generated through a macro

How to declare array of structs in C

I am having trouble declaring an array of structs prior to populating them with data.
My struct looks like this:
typedef struct {
uint8_t * p_data; ///< Pointer to the buffer holding the data.
uint8_t length; ///< Number of bytes to transfer.
uint8_t operation; ///< Device address combined with transfer direction.
uint8_t flags; ///< Transfer flags (see #ref NRF_TWI_MNGR_NO_STOP).
} nrf_twi_mngr_transfer_t;
And in my code I am trying to declare the array like this:
struct nrf_twi_mngr_transfer_t start_read_transfer[10];
However I get a compile error:
array type has incomplete element type 'struct nrf_twi_mngr_transfer_t'
I have searched around as I thought should be a common thing, but I can't figure out what I am doing wrong. Maybe because one of the elements is a pointer? But that pointer should be a fixed size right?
Many thanks
It looks like some explanations are in order. This code
typedef struct {
//...
} nrf_twi_mngr_transfer_t;
Already defines a type which can be used directly. In contrast,
struct nrf_twi_mngr_transfer_struct {
//...
};
Would define a struct name, and to access it you'd need to indicate that you are referring to a struct.
As a result, given two definitions above, you should define your arrays differently:
nrf_twi_mngr_transfer_t arr[10]; // if using typedef
struct nrf_twi_mngr_transfer_struct arr2[10]; // if using struct with no typedef
And just in case you are wondering,
struct {
//...
} nrf_twi_mngr_transfer_obj;
Defines an object of anonymous struct type.

C structure multiple types

I'd like to write a library in C and I don't know what is the recommended way. I got for example structure and multiple functions like this:
typedef struct example
{
int *val;
struct example *next;
} Example;
and I have build function for multiple types of val
Example* build() { do sth };
Example* buildf() { do sth }; // val is float
Example* buildd() { do sth }; // val is double
What is the better practice (used in "professional" library). Use pointer to void and casting or have structure for all possibilities - int, float, double.
Use a union and some way to store type info:
typedef struct example
{
enum{ T_STRUCT_WITH_INT, T_STRUCT_WITH_FLOAT, T_SO_ON } type;
union {
int val_int;
float val_float;
} val;
struct example *next;
} Example;
Access fields after checking type by s->val.val_int
In C11 you can have union anonymous and fields can be accessed like s->val_int
This is primarily based on some combination of opinion, experience and the specific requirements at hand.
The following approach is possible, inspired by some container library work by Jacob Navia. I've never used it myself:
struct container_node {
struct container_node *link_here, *link_there, *link_elsewhere;
/*...*/
char data[0]; /* C90 style of "flexible array member" */
};
struct container_node *container_node_alloc(size_t data_size);
The allocation function allocates the node large enough so that data[0] through data[data_size-1] bytes of storage are available. Through another set of API functions, user data of arbitrary type be copied in and out.
The following approach is sometimes called "intrusive container". The container defines only a "base class" consisting of the link structure. The user must embed this structure into their own structure:
struct container_node {
struct container_node *next, *prev;
};
void container_insert(struct container *container, struct container_node *n);
struct container_node *container_first(struct container *container);
The user does this:
struct my_widget {
struct container_node container_links;
int widget_height;
/* ... */
};
/* .... */
/* We don't insert my_widget, but rather its links base. */
container_insert(&widg_container, &widget->container_links);
Some macros are used to convert between a pointer to the widget and a pointer to the container links. See the container_of macro used widely in the Linux kernel:
struct my_widget *wptr = container_of(container_first(&widg_container),
struct my_widget, container_links);
See this question.
Then there approaches of storing a union in each node, which provides an integer, floating-point-value or a pointer. In that case, the data is separately allocated (though not necessarily: if the caller controls the allocation of the nodes, it's still possible to put the node structure and the user data in a buffer that came from a single malloc call).
Finally, there are also approaches which wrap these techniques with preprocessor templating, an example of which are the BSD QUEUE macros.

Document C in Doxygen despite usage of macros?

I have macros in C source files that generate function declarations as well as for structures.
I made the decision to use doxygen in order to document them, but as long as my source file does not explicitly contain the declaration, doxygen is not generating the appropriate documentation.
Here is a little example; I have a macro that is a kind of idiom for a class declaration:
#define CLASS(x) \
typedef struct _##x x; \
typedef struct _##x *P##x; \
typedef struct _##x **PP##x; \
typedef struct _##x
So instead of writing:
/**
* \struct _Vector
* \brief the vector structure handles stuff to store data accessible by an index.
*/
typedef struct _Vector {
/*#{*/
Container container; /**< inherits from container */
size_t allocated_size; /**< the total allocated size of a vector (private usage) */
void* elements; /**< pointer to the allocated memory space (private usage) */
/*#}*/
} Vector, *PVector;
I may write instead:
/**
* \struct _Vector
* \brief the vector structure handles stuff to store data accessible by an index.
*/
CLASS(Vector) {
/*#{*/
Container container; /**< inherits from container */
size_t allocated_size; /**< the total allocated size of a vector (private usage) */
void* elements; /**< pointer to the allocated memory space (private usage) */
/*#}*/
};
But for the second case, doxygen does not generate the documentation regarding my struct members.
How could I find a compliant solution to such an issue?

Resources