I've been at this for several days now, unable to compile successfully. I made a very-oversimplified project separate from my main one. Depending which embeded struct I comment out, I get one of the following errors:
file: x2d_gfx_speech_balloon.h
error C2079: 'sprBalloon' uses undefined struct 'X2D_SPRITE'
error C2079: 'font' uses undefined struct 'X2D_FONT'
Side note: Putting the sprite and font headers from the common header into the speech balloon header itself has no effect either.
I'm going to provide the entire simplified code below. Please let me know if you see any syntax wrong, and optionally, feel free to compile it on your side if it helps. My environment is Windows 7 with Visual Studio 2010 and using C89.
main.c
#include "common.h"
int main(void)
{
return 0;
}
common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#include <stdlib.h>
#include "constants.h"
#include "X2D_GFX_Sprite.h"
#include "X2D_GFX_Font.h"
#include "X2D_GFX_Speech_Balloon.h"
#endif
constants.h
#ifndef _CONSTANTS_H_
#define _CONSTANTS_H_
/* General Constants */
#define TRUE 1
#define FALSE 0
#endif
X2D_GFX_Font.h
#ifndef _X2D_GFX_FONT_H_
#define _X2D_GFX_FONT_H_
#include "common.h"
/* Font Structure */
struct X2D_FONT
{
float x, y;
int size;
int blnShow;
};
/* Font Prototypes (not shown here)... */
int fnt_init(struct X2D_FONT *objFont, const char *strFileName,
const char *strText, const float x, const float y,
const unsigned int size);
#endif
X2D_GFX_Font.c
#include "X2D_GFX_Font.h"
int fnt_init(struct X2D_FONT *objFont, const char *strFileName,
const char *strText, const float x, const float y,
const unsigned int size)
{
return TRUE;
}
X2D_GFX_Sprite.h
#ifndef _X2D_GFX_SPRITE_H_
#define _X2D_GFX_SPRITE_H_
#define MAX_VARSI 10
#include "common.h"
struct X2D_SPRITE
{
float x;
float y;
unsigned int width;
unsigned int height;
int blnShow;
float vx, vy;
float angle;
int varsi[MAX_VARSI];
};
int spr_init(struct X2D_SPRITE *spr, const char *strFileName);
#endif
X2D_GFX_Sprite.c
#include "X2D_GFX_Sprite.h"
int spr_init(struct X2D_SPRITE *spr, const char *strFileName)
{
return TRUE;
}
X2D_GFX_SPEECH_BALLOON.h
#ifndef _X2D_GFX_SPEECH_BALLOON_H_
#define _X2D_GFX_SPEECH_BALLOON_H_
#include "common.h"
/* Contains a list of acceptable balloon types */
enum ESpeechBalloonType
{
ESpeechBalloonType_Talk,
ESpeechBalloonType_Thought,
ESpeechBalloonType_Yell,
ESpeechBalloonType_Whisper
};
/* Speech Balloon types */
struct X2D_SPEECH_BALLOON
{
struct X2D_SPRITE sprBalloon;
struct X2D_FONT font;
enum ESpeechBalloonType eBalloonType;
};
#endif
X2D_GFX_SPEECH_BUBBLE.c
#include "X2D_GFX_SPEECH_BALLOON.h"
Your issue is the order in which files are included, specifically in X2D_GFX_Sprite.c. If you run just the preprocessor on that file (in Linux you can use cpp or gcc -E, I don't know how in Windows) and scroll down to the very end, you'll find that the X2D_SPRITE struct is being declared after it's used:
struct X2D_SPEECH_BALLOON
{
struct X2D_SPRITE sprBalloon;
struct X2D_FONT font;
enum ESpeechBalloonType eBalloonType;
};
# 11 "common.h" 2
# 7 "X2D_GFX_Sprite.h" 2
struct X2D_SPRITE
{
float x;
float y;
unsigned int width;
unsigned int height;
int blnShow;
float vx, vy;
float angle;
int varsi[10];
};
Two easiest ways to fix it would be to either not use common.h or move #include "common.h" after the struct declaration in X2D_GFX_Sprite.h.
This happens because X2D_GFX_Sprite.c includes X2D_GFX_Sprite.h, which includes common.h, which includes the other .h files. The preprocessor first copies in X2D_GFX_Sprite.h. When it finds #include "common.h", it begins copying that file. The first three includes are copied in. When it gets back to X2D_GFX_Sprite.h, it'll copy it in, but the header guards will get rid of everything in it. Next, it copies in X2D_GFX_Font.h and X2D_GFX_Speech_Balloon.h, which includes the X2D_SPEECH_BALLOON struct, in that order. Only then does it finally add in the rest of X2D_GFX_Sprite.h, including the X2D_SPRITE struct. This results in the two structs not being copied in the correct order.
Related
This is a question that I have been reading a lot about but I am still unclear how things work as I am getting building errors or incomplete type lint errors.
I have a project requiring opengl that I am writing low level opengl function, then I want to build on top of those translation [here after referred to as TU] units to build more higher level TU.
for example.
I have a common_structs.h that defines a few things like this:
common_structs.h
#ifndef COMMON_STRUCTS_H
#define COMMON_STRUCTS_H
#include <OpenGL.h>
struct renderable_2D {
...
float angle;
GLshort vertex_count;
GLfloat vertices[12];
GLfloat colors[16];
GLshort indices[6];
GLfloat tex_coords[8];
...
};
struct texture_2D {
...
GLuint texture_id;
...
};
struct default_shader {
const char* vertex_shader_srouce;
const char* fragment_shader_source;
GLuint shader_program;
};
struct camera_2D {....};
#endif /* COMMON_STRUCTS_H */
I declared these structs in their own header file to avoid circular dependencies.
This file isn't compiled but I need to #include opengl to clear the lint warnings for the GLtypes.
Next up there are header and source TU that implement the functionality for these types. Typically
Let's look at renderable_2D for example:
#ifndef RENDERABLE_2D_H
#define RENDERABLE_2D_H
#include "../../common/common_structs.h" //include the definition of renderable_2d
struct renderable_2D* ren2d_new(void);
struct renderable_2D* ren2d_set_uv(struct renderable_2D* out, const float uv[]);
struct renderable_2D* ren2d_set_tint(struct renderable_2D* out, const float r,
const float g, const float b,
const float a);
struct renderable_2D* ren2d_set_alpha(struct renderable_2D* out, const float a);
struct renderable_2D* rend2d_set_z_index(struct renderable_2D* out,
const int index);
struct renderable_2D* rend2d_set_angle(struct renderable_2D* out,
const float angle);
#endif /* RENDERABLE_2D_H */
and the some of the source file for this:
#include "../headers/renderable_2D.h"
#include <stdlib.h>
this file includes the header and implement the functions. Next there's one more header only file.
core_graphics.h
#ifndef CORE_GRAPHICS_H
#define CORE_GRAPHICS_H
#include "renderable_2D/headers/renderable_2D.h"
#include "default_shader/headers/default_shader_2D.h"
#include "default_camera_2D/headers/default_camera_2D.h"
#endif /* CORE_GRAPHICS_H */
this is a header only TU again and will include all the sub TU that make up this part of the library. It's supposed to be built as a shared library so next up the ladder is another shared library that will
#include core_graphics/core_graphics.h
this is where the problem comes in. Say I have another TU main.c, main looks like this.
main.c
#include "core_graphics/core_graphics.h"
#include <stdlib.h>
int main(int argc, char* argv[])
{
struct renderable_2D* rend = (struct renderable_2D*)calloc(1, sizeof(struct renderable_2D));
return 0;
}
the line where I try to calloc the struct I get lint errors saying
invalid application of 'sizeof' to an incomplete type 'struct renderable_2d'
now incomplete types says it cant find the definition of the struct renderable_2D but, from the source listed above, should it get included?
core_graphics.h has the definition of common_structs.h which holds the definition of the struct?
struct renderable_2D --> common_structs.h --> core_graphics.h --> main.c
okay, ive searched a solution for like two days now but i couldnt find whats going wrong with my code. ;(
The task is simple: define a new type using typedef and have a function read out lines of this new type from a file into an array of again this new type. so my typedef inside the headerfile looks like this right now (ive tried several variants of writing this)
// filename: entries.h
#ifndef ENTRIES_H_
#define ENTRIES_H_
#include<time.h>
typedef struct{
char Loginname[25];
time_t RegDate;
unsigned long Highscore;
time_t Hdate;
}typePlayerEntry;
int readPlayerList(char *name, typePlayerEntry *feld);
#endif /* ENTRIES_H_ */
the main.c:
//filename: main.c
#include <stdio.h>
#include "entries.h"
int main(void) {
char name[13]="numbers.txt";
typePlayerEntry *pep;
readPlayerList(name, pep);
return 0;
}
my function file looks like this (and heres where the error is shown)
//filename: readPlayerList.c
int readPlayerList(char *name, typePlayerEntry *feld) {
return 0;
}
irrelevant code is completely left out. The problem is reproducable with the code posted.
the program wont compile because the type of the second argument in the function file could not be recognized,
- which is odd, because its defined in the header file and also usable in the main function.
And this error is somehow connected to the declaration of (in this case) a pointer of type playerEntry in my main.c. So if i do not declare it, theres no error, though i have to declare it to actually give it to the function. how come that the solution so far is to include the entries.h into the readPlayerList.c, which wasnt neccesary for previous functions?
im using eclipse kepler with MinGW, in case thats a compiler issue.
corrected the missing include of time.h and adjusted the code a little.
You are missing #include <time.h> in entries.h.
// filename: entries.h
#ifndef ENTRIES_H_
#define ENTRIES_H_
typedef struct {
char Loginname[25];
time_t RegDate; /* from <time.h> */
unsigned long Highscore;
time_t Hdate; /* from <time.h> */
} playerEntry;
int readPlayerList(char *name, playerEntry *feld);
#endif /* ENTRIES_H_ */
And you need to #include "entries.h" in readPlayerList.c
//filename: readPlayerList.c
int readPlayerList(char *name, typePlayerEntry *feld) {
/* ^^^^^^^^^^^^^^^ from entries.h */
return 0;
}
part of the problem is the compiler is seeing (at least) two different meanings/definitions for the 'playerEntry' name.
Suggest:
1) eliminate the 'typedef' statement
(it is just cluttering the code and confusing the compiler)
2) properly reference the struct via:
'struct playerEntry' instead of 'playerEntry'
in TheHeader.h file:
struct playerEntry
{
char Loginname[25];
time_t RegDate;
unsigned long Highscore;
time_t Hdate;
};
int readPlayerList(char *name, struct playerEntry *feld);
in the source file:
#include "TheHeader.h"
int readPlayerList(char *name, struct playerEntry *feld)
{
return 0;
}
I'm trying to Build this project in CodeBlocks so that I can step through one of the functions, but I'm having trouble building it. This is my error
||=== Build: Debug in MAGLAT (compiler: GNU GCC Compiler) ===|
obj\Debug\GMCORD.o||In function `GM_CartesianToSpherical':|
C:\Users\Guest\SkyDrive\temp\MAGLAT\MAGLAT\GM_SubLibrary.c|11|multiple definition of `GM_CartesianToSpherical'|
obj\Debug\GM_SubLibrary.o:C:\Users\Guest\SkyDrive\temp\MAGLAT\MAGLAT\GM_SubLibrary.c|11|first defined here|
//HEADER FILE
#ifndef GMHEADER_H
#define GMHEADER_H
#endif
#ifndef M_PI
#define M_PI ((2)*(acos(0.0)))
#endif
#define GM_STARTYEAR 1900
#define RAD2DEG(rad) ((rad)*(180.0L/M_PI))
#define DEG2RAD(deg) ((deg)*(M_PI/180.0L))
#define ATanH(x) (0.5 * log((1 + x) / (1 - x)))
#define MU_0 4*M_PI / 10000000
#define R_e 6.371 * 1000000
#define TRUE ((int)1)
#define FALSE ((int)0)
typedef struct {
int Day;
int Month;
int Year;
double DecimalYear;
int DayNumber;
} GMtype_Date;
typedef struct {
double lambda;// longitude
double phi; // geodetic latitude
double HeightAboveEllipsoid; // height above the ellipsoid (HaE)
} GMtype_CoordGeodetic;
typedef struct {
...
...
}...;
//GM Cord functions
void GM_CartesianToSpherical(GMtype_CoordCartesian CoordCartesian, GMtype_CoordSpherical *CoordSpherical);
///GM_SubLibrary.c
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "GMHeader.h"
void GM_CartesianToSpherical(GMtype_CoordCartesian CoordCartesian, GMtype_CoordSpherical *CoordSpherical)
{
/*This function converts a point from Cartesian coordinates into spherical coordinates*/
double X, Y, Z;
X = CoordCartesian.x;
Y = CoordCartesian.y;
Z = CoordCartesian.z;
CoordSpherical->r = sqrt(X * X + Y * Y + Z * Z);
CoordSpherical->phig = RAD2DEG(asin(Z / (CoordSpherical->r)));
CoordSpherical->lambda = RAD2DEG(atan2(Y, X));
} /*GM_CartesianToSpherical*/
///GMCORD.c
//----------------------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "GM_SubLibrary.c"
//----------------------------------------------------------------------------------------
int main()
{
int Flag = 1;
char ans[20];
GMtype_Date date;
GMtype_Data G0, G1, H1;
GMtype_CoordGeodetic location;
GMtype_CoordDipole GMlocation;
GMtype_Ellipsoid Ellip;
GM_ScanIGRF(&G0, &G1, &H1);
GM_SetEllipsoid(&Ellip);
while(Flag == 1) {
GM_GetUserInput(&location, &date);
GM_CORD(location, &date, Ellip, G0, G1, H1, &GMlocation);
GM_PrintUserData(location, date, GMlocation);
...
}
return 1;
}
You are including the C source file GM_SubLibrary.c in GMCORD.c instead of the header file GMHeader.h.
See: Including one C source file in another?
You shouldn't #include c files, only headers. You get this error because your GMCORD.c essentially includes all the code from GM_SubLibrary.c already, so if you compile both files in the same project you get that code defined twice
the #include directive puts all the text from the included file into the present file. If you compile GM_SubLibrary.c as a standalone module (which you do, since the compiler noticed the .o file of that name), then you end up with the same code being compiled twice.
When the linker tries to figure out what function to call, it can't tell the two definitions apart. It is not clever enough to see that the definition is identical, just that you appear to give two sets of instructions "when I call function X, do Y".
You probably meant to include a .h file instead.
Error 2 error C2371: 'QixC': redefinition; different basic types line 5
Error 5 error C2371: 'QixC': redefinition; different basic types line 5
Error 13 error C2371: 'QixC': redefinition; different basic types line 5
This is the part of the file Game.h:
#include "Graphics_Console.h"
#include <stdio.h>
#include <conio.h>
typedef struct
{
int X;
int Y;
}QixC;
typedef struct
{
int X;
int Y;
}CCursor;
And I use them in Game.c :
#include "Game.h"
#include <stdio.h>
#include <conio.h>
#include <time.h>
int QIX(int nivell)
{
QixC Qix;
CCursor Cursor;
HANDLE hScreen;
int DirQixX,DirQixY;
int IniciX,IniciY;
int FiX, FiY;
int DirStix=0;
int Area=0,AreaTotal=0,AreaObjectiu=(FI_X-INICI_X)*(FI_Y-INICI_Y)*0.75;
int Pantalla=1;
int Puntuacio=0;
int tecla=0;
int viu=1;
int NCops=0, Velocitat=1000/(nivell*0.70);
int XocStix=0;
char continuar[1];
hScreen = GetStdHandle(STD_OUTPUT_HANDLE);
InitScreen(hScreen);
do
{
system("CLS");
IniciX=INICI_X,IniciY=INICI_Y;
FiX=FI_X, FiY=FI_Y;
Cursor.X=INICI_X+(FiX-INICI_Y)/2,Cursor.Y=FI_Y;
DibuixarRectangle(IniciX,IniciY,FI_X,FI_Y,hScreen);
InfoPuntsPartida(hScreen, Puntuacio);
InfoPantallaPartida(hScreen, Pantalla);
Qix.X=Aleatori(IniciX+1,FiX-1),Qix.Y=Aleatori(IniciY+1,FiY-1);
InicialitzarDirQix(&DirQixX,&DirQixY);
PintarQix(Qix,hScreen);
PintarCursor(Cursor.X,Cursor.Y,hScreen);
do{
if(_kbhit())
{
tecla=LlegirEvent();
TractarEvent(tecla,Cursor,&IniciX,&IniciY,&FiX,&FiY,Qix,&DirStix,&Area,hScreen);
if(Area)
{
Puntuacio=Puntuacio+Area;
AreaTotal+=Area;
Area=0;
InfoPuntsPartida(hScreen,Puntuacio);
}
}
NCops++;
if(NCops==Velocitat)
{
if(DirStix!=0)
XocStix=QiXXocStiX(Qix,Cursor,DirStix);
if(!XocStix)
MoureQix(Qix,&DirQixX,&DirQixY,IniciX,IniciY,FiX,FiY,hScreen);
else
viu=0;
NCops=0;
}
}while((tecla!=TECLA_q)&&(tecla!=TECLA_Q)&&viu &&(AreaTotal<AreaObjectiu));
GameOver(hScreen);
TextColor(LIGHTGREY,BLACK,hScreen);
GotoXY(0,FI_Y+1,hScreen);
return Puntuacio;
system ("PAUSE");
printf("Continuar?(s/n)");
scanf("%c",&continuar);
}while(continuar!="s");
}
Sorry for the foreign words and names, english is not my first language.
I can't see where is redefined. They don't appear anywhere else,but are passed as parameters to some functions. Any help, please?
Try guarding your header against multiple inclusion.
#ifndef GAME_H
#define GAME_H
#include "Graphics_Console.h"
#include <stdio.h>
#include <conio.h>
typedef struct
{
int X;
int Y;
}QixC;
typedef struct
{
int X;
int Y;
}CCursor;
#endif /* GAME_H */
By default, if you include multiple headers which directly or indirectly include your header, you'll get multiple competing (if identical) versions of its structures and functions. You can avoid this by starting your header
#ifndef SOMETHING_UNIQUE_TO_YOUR_HEADER
#define SOMETHING_UNIQUE_TO_YOUR_HEADER
and ending it
#endif /* SOMETHING_UNIQUE_TO_YOUR_HEADER */
which guarantees that any source file will include at most a single copy of your structures.
I am trying to make the s_cord_print function visible in the cord_s.c file only. Currently the function is visible/runnable in main.c even when it is declared static.
How do I make the s_cord_print function private to cord_s.c?
Thanks!
s_cord.c
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
void* VOID_THIS;
#define $(EL) VOID_THIS=&EL;EL
static s_cord s_cord_print(){
struct s_cord *THIS;
THIS = VOID_THIS;
printf("(%d,%d)\n",THIS->x,THIS->y);
return *THIS;
}
const s_cord s_cord_default = {1,2,s_cord_print};
main.c
#include <stdio.h>
#include <stdlib.h>
#include "s_cord.c"
int main(){
s_cord mycord = s_cord_default;
mycord.x = 2;
mycord.y = 3;
$(mycord).print().print();
//static didn't seem to hide the function
s_cord_print();
return 0;
}
~
The problem is:
#include "s_cord.c"
You should remove that. Instead, create a s_cord.h file that contains only declarations, such as:
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
and put:
#include "s_cord.h"
in main.c and s_cord.c. You also need an extern declaration for s_cord_default. So the complete code is:
s_cord.c:
#include "s_cord.h"
#include <stdio.h>
void* VOID_THIS;
static s_cord s_cord_print(){
struct s_cord *THIS;
THIS = VOID_THIS;
printf("(%d,%d)\n",THIS->x,THIS->y);
return *THIS;
}
const s_cord s_cord_default = {1,2,s_cord_print};
s_cord.h:
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
#define $(EL) VOID_THIS=&EL;EL
extern const s_cord s_cord_default;
extern void *VOID_THIS;
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "s_cord.h"
int main(){
s_cord mycord = s_cord_default;
mycord.x = 2;
mycord.y = 3;
$(mycord).print().print();
return 0;
}
You'll now get a error if you try to call s_cord_print() from main, as expected.
EDIT: I forgot to move the $(EL) definition, and it needed an extern for VOID_THIS.
EDIT 2: The correct compilation command is:
gcc s_cord.c main.c -o main
When you include s_cord.c from within main.c, the compiler sees your program as one big file. It doesn't treat the included file as separate. To make them separate, you have to compile them separately. Once you have compiled them separately, you will then have to link them to create the whole program.
When you try to compile each part, you will get errors, because each file doesn't know about the code in the other file. Remember, this is what you were trying to accomplish with that one function. Well, now you've got what you asked for, many times over. Now, you have to create header files that explain the "missing parts". Generally the files being compiled look at each other's ".h" files (they #include them) to get a bearing on the "missing" (actually, external) parts. These are declarations, which tell the compiler "pretend you already know about this, and I promise that when we link everything, it will be provided".