I have two header files that refer to each other and that produce a compile error if I do not carefully put my includes on the right lines. Each of my header files matches with a srcs directory:
___include
|____matrixes.h
|____define.h
|____transformations.h
|____tuples.h
|____pixels.h
|____ppm.h
|____Myproject.h
|____error_handler.h
|____graphics.h
Basically, Myproject.h contains all #include I needed, while every other header files contain prototypes, typedefs, structs, #defines I needed for the respective srcs directory. But I guess I got something wrong. My problem comes from pixels.h, graphics.h and (maybe) Myproject.h. Here are they:
#ifndef PIXELS_H
# define PIXELS_H
# include "Myproject.h"
typedef uint32_t t_pixel;
typedef unsigned char t_color;
//////////////////////////
//# include "graphics.h"
//////////////////////////
// pixels/conversions.c
t_tuple pixel_to_point(t_image image, int i, int j);
t_tuple point_to_pixel(t_image image, double x, double y);
// pixels/print.c
void print_pixel(t_pixel p, char *name);
// pixels/pixels.c
t_pixel pixel(t_color r, t_color g, t_color b, t_color a);
t_color get_a(t_pixel pixel);
t_color get_r(t_pixel pixel);
t_color get_g(t_pixel pixel);
t_color get_b(t_pixel pixel);
// pixels/ops.c
t_pixel add_pixel(t_pixel p, t_pixel q);
t_pixel sub_pixel(t_pixel p, t_pixel q);
t_pixel scal_pixel(float q, t_pixel p);
t_pixel mul_pixel(t_pixel p, t_pixel q);
#endif
#ifndef GRAPHICS_H
# define GRAPHICS_H
# include "Myproject.h"
typedef struct s_window{
void *mlx;
void *win;
} t_window;
typedef struct s_image {
void *mlx;
void *img;
char *addr;
int bits_per_pixel;
int line_length;
int endian;
t_tuple origin;
t_tuple extension;
} t_image;
typedef struct s_canvas{
t_window window;
t_image image;
} t_canvas;
// graphics/graphics.c
t_window *window(t_window *cvs);
t_image *image(t_image *img, void *mlx);
t_canvas *canvas(t_canvas *canvas);
void put_pixel(t_image img, int x, int y, t_pixel pixel);
// graphics/free.c
void free_window(t_window *window);
void free_image(t_image *image);
void free_canvas(t_canvas *canvas);
#endif
#ifndef MYPROJECT_H
# define MYPROJECT_H
# include <unistd.h>
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <limits.h>
# include <stdbool.h>
# include <mlx.h>
# include <math.h>
# include <fcntl.h>
# include <sys/stat.h>
# include "libft.h"
# include "define.h"
# include "tuples.h"
# include "matrixes.h"
# include "pixels.h"
# include "graphics.h"
# include "ppm.h"
# include "error_handler.h"
# include "transformations.h"
#endif
As such, it did not compile with following error:
In file included from srcs/pixels/conversions.c:13:
In file included from include/miniRT.h:30:
include/pixels.h:22:24: error: unknown type name 't_image'
t_tuple pixel_to_point(t_image image, int i, int j);
^
include/pixels.h:23:24: error: unknown type name 't_image'
t_tuple point_to_pixel(t_image image, double x, double y);
I understand the error because the pixel_to_point function takes a t_image as argument and in Myproject.h, graphics.h is included after pixels.h so it does not recognize the t_image type.
If I try to invert the graphics.h and pixels.h includes in Myproject.h, I just get the same error when a function from graphics.h needs the t_pixel type.
I can make it run by uncommenting the commented #include graphics.h in pixels.h (because it is AFTER the t_pixel typedef) but I feel it is an ugly method.
Is there a rule to follow to avoid these issues ?
CodePudding user response:
Consider your project include files to form some sort of hierarchy.
Have pixel.h
only include "tuples.h"
, etc. What is needed, not "Myproject.h"
.
Likewise for "graphics.h"
.
Other strategies exist.
IMO, typedef unsigned char t_color;
should not exist in "pixels.h"
, but only in "color.h"
.
IOWs, I recommend that each object/function/constant/macro declared in a xyz.h
begin with a xyz_
or the like. OP's current approach has names spaces all over the place defined in a given .h
file. I see this as hard to follow and unnecessarily difficult to maintain.
I would also recommend to rename functions like add_pixel()
to pixel_add()
to lead with the key-prefix pixel.