Sotiris Kettenis
Sotiris Kettenis

Reputation: 49

I receive a compiling error while trying to compile my code

I'm creating a program for my semester project which takes a bitmap image in .pbm format, simplifies it via Bezier curves and outputs the result in .eps format. The university suggested that we work on the project with variable size arrays and has already given the declarations.

The struct for the variable size array of quadratic Beziers is:

typedef struct TTV_Bezier2_
{
  UINT nb;
  UINT cap;
  UINT taille_elt;
  Bezier2 * tab;
}TTV_Bezier2;

UINT is a declaration given from the university (typedef unsigned int) Bezier2 is a type created by me. It's the represantation of a quadratic Bezier in my program defined by its 3 control points:

typedef struct Bezier_q
{
    Point C0;
    Point C1;
    Point C2;
}Bezier2;

Point is another typedef struct :

typedef struct Point_ {
    double x,y;
} Point;

Heres my problem: The variable size array of Beziers is defined inside a file named TTV_Bezier.h and the Bezier2 type is defined inside a file called bezier.h. I have included the files to each other because they each file uses these types from the other. When compiling however I get the following error:

gcc -c -g -O2 -Wall -I. test_simplification_bezier2.c

In file included from TTV_Bezier2.h:8,
  from test_simplification_bezier2.c:8:
  bezier.h:91:1: error: unknown type name ‘TTV_Bezier2’; did you mean ‘Bezier2’?
  TTV_Bezier2 * simplification_douglas_peucker_bezier2(TTV_Point CONT, int j1, int j2, double d);

I was told that there's a problem with my dependancies inside the Makefile but I don't think so cause I've already included them to the right files. Can you help me please?

Files:

TTV_Bezier2.h:

#ifndef _TTV_BEZIER2_H_
#define _TTV_BEZIER2_H_

#include <stdio.h>
#include <stdlib.h>

#include "types_macros.h"
#include "bezier.h"

typedef struct TTV_Bezier2_
{
    UINT nb;
    UINT cap;
    UINT taille_elt;
    Bezier2 * tab;
}TTV_Bezier2;

TTV_Bezier2 * creer_TTV_Bezier2_vide();

Bezier2 element_TTV_Bezier2(TTV_Bezier2 T, UINT i);

UINT nb_elements_TTV_Bezier2(TTV_Bezier2 * T);

TTV_Bezier2 * ajouter_element_TTV_Bezier2(TTV_Bezier2 * T, Bezier2 e);

TTV_Bezier2 * concatener_TTV_Bezier2(TTV_Bezier2 * T1, TTV_Bezier2 * T2);

void supprimer_TTV_Bezier2(TTV_Bezier2 *ptr_T);

#endif

bezier.h:

#ifndef _BEZIER_H_
#define _BEZIER_H_

#include "TTV_Bezier2.h"
#include "TTV_Point.h"
#include "geom2d.h"

//Definition du type Bezier2
typedef struct Bezier_q
{
    Point C0;
    Point C1;
    Point C2;
}Bezier2;

//Definition du type Bezier3
typedef struct Bezier_s
{
    Point C0;
    Point C1;
    Point C2;
    Point C3;
}Bezier3;

//Fonction qui calcule le point de la Bezier quadratique C(t) au parametre t
Point calculate_bezier_2(Bezier2 b, double t);

//Fonction qui calcule le point de la Bezier cubique C(t) au parametre t
Point calculate_bezier_3(Bezier3 b, double t);

//Fonction qui calcule la distance entre un point et une bezier quadratique
double distance_point_bezier2(Point P, Bezier2 B, double t);

//Fonction qui calcule la distance entre un point et une bezier cubique
double distance_point_bezier3(Point P, Bezier3 B, double t);

//Fonction qui calcule le factoriel d'un nombre
double factorial (int i);

//Fonction qui prend une Bezier quadratique et la transforme en Bezier cubique
Bezier3 convert_bezier2_to_3(Bezier2 b);

//Fonction qui calcule la base bernstein B(i,d,t)
double calculate_bernstein_base(int i, int d, double t);

//Fonction qui calcule γ(k)
double calculate_gamma(int i, int n);

//Fonction qui approxime la sequence de points CONT par une Bezier quadratique
Bezier2 approx_bezier2(Point * tab, int j1, int j2);

//Fonction qui approxime la sequence de points CONT par une Bezier cubique
Bezier3 approx_bezier3(Point * tab, int j1, int j2);

//Fonction qui simplifie le contour avec une Bezier cubique
Bezier3_t * simplification_douglas_peucker_bezier3(Point * CONT, int j1, int j2, double d);

//Fonction qui simplifie le contour avec une Bezier quadratique
TTV_Bezier2 * simplification_douglas_peucker_bezier2(TTV_Point CONT, int j1, int j2, double d);

#endif /* _BEZIER_H_ */

test_simplification_bezier2.c :

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "image_pbm.h"
#include "geom2d.h"
#include "TTV_Point.h"
#include "TTV_Bezier2.h"
#include "calcul_contours_multiples.h"

int main(int argc, char * argv[])
{
    if (argc != 4)
    {
        printf("Usage: ./test_simplification_bezier <source.pbm> <destination.eps> <distance_seuil>\n");
        return 0;
    }
    
    FILE * f;
    double distance_seuil;
    int i = 0;
    Image M, P;
    Point init;
    TTV_Point contour;
    TTV_Bezier2 * L;
    
    L = creer_TTV_Bezier2_vide();
    contour = creer_TTV_Point_vide();
    
    f = fopen(argv[2], "w");
    distance_seuil = atof(argv[3]);
    
    //Lecture de l'image
    M = lire_fichier_image(argv[1]);
    
    //Creation de l'image masque
    P = create_mask_image(M);
    
    fprintf(f, "%%!PS-Adobe-3.0 EPSF-3.0\n%%%%BoundingBox: 0 0 %d %d\n0 setlinewidth\n", M.L, M.H);
    while(is_empty(P) == -1)
    {
        init = trouver_point_init(P);
        contour = trouver_pixel_depart_TTV(M,P,init);
        while(i < nb_elements_TTV_Point(contour))
        {
            contour.tab[i].y = fabs((double) M.H - contour.tab[i].y);
            i++;
        }
        i = 0;
        L = simplification_douglas_peucker_bezier2(contour, 0, nb_elements_TTV_Point(contour) - 1, distance_seuil);
        write_to_file_bezier2(L,f);
    }
    fprintf(f, "\nfill\nshowpage");
    fclose(f);
    return 0;
}

Upvotes: 0

Views: 159

Answers (2)

Shawn
Shawn

Reputation: 721

You have a circular dependency between bezier.h and TTV_Bezier2.h

If you think about the prepocessor #include function as simply flattening out the source code into one giant file for the compiler, starting from main.c:

  • main includes (among others) TTV_Bezier.h
  • TTV_Bezier.h includes bezier.h before defining or declaring TTV_Bezier2
  • bezier.h will include TTV_Bezier.h, but it will have no effect because of the include guards (and that's a good thing)

If you imagine the flattened preprocessor output in the compiler's memory, the contents of bezier.h are present before any mention of TTV_Bezier, so you get the error that you're seeing.

To fix this you can either:

  • Move the TTV_Bezier2 * simplification_douglas_peucker_bezier2 prototype to TTV_Bezier2.h
  • OR Move the structures that are needed for both headers into a new third header, and include that in both.
  • or do what's in bruno's answer and forward declare the struct

Upvotes: 1

bruno
bruno

Reputation: 32586

in TTV_Bezier2.h you include bezier.h and in bezier.h you include TTV_Bezier2.h, this is the source of your problem

but in bezier.h you do not need to know the exact definition of TTV_Bezier2 because you only reference it via pointer, so in bezier.h :

  • remove #include "TTV_Bezier2.h"
  • add struct TTV_Bezier2_;
  • replace the return type of simplification_douglas_peucker_bezier2 by struct TTV_Bezier2_ *

And add #include "TTV_Bezier2.h" in the sources when needed

Upvotes: 2

Related Questions