i'm doing a simple project in C in which, for the moment, i use two structs: Player and Card.
I have created the 2 struct in different header files, because functions in Player use Card, but also other elements that I haven't already done.
When I try to use getId() in Player, the VSCode's compiler says:
reference to external symbol _getId not resolved in _discardCard()
card.h code is:
#include <stdbool.h>
typedef struct card{
int id;
bool black;
int numElems;
char* text[3];
}card;
card* initCard(int id,bool black,char* text[],int numElems)
int getId(card* c);
card.c code is:
#include "carta.h"
#include<stdio.h>
#include <stdbool.h>
#include <stdlib.h>
...
int getId(carta* c){
return c->id;
}
Instead the code for Player.h is:
#include "card.h"
#define CARDSMAX 5
typedef struct{
bool master;
int id;
int points;
char* nickname;
card* cards[CARDSMAX];
int NumCards;
}player;
... //other functions
card* discardCard(int id,player* g);
The code for Player.c is:
#include "player.h"
#include <stdio.h>
#include <stdlib.h>
player* initPlayer(char* nickname,int id){
player* g=(player*) malloc(sizeof (player));
g->id=id;
g->nickname=nickname;
g->master=false;
g->points=0;
g->NumCards=0;
for(int i=0;i<CARDSMAX;i++){
g->cards[i]=(card*)malloc(sizeof(card));
}
return g;
}
....
card* DiscardCard(int id,player* g){
for(int i=0;i<CARDSMAX;i++){
card* c=g->cards[i];
if(getId(c)==id){
card* e= g->cards[i];
g->cards[i]=NULL;
g->NumCards--;
return e;
}
}
return NULL;
}
Can someone help me? (If you see some inconsistency in the code, it'is because i tried a fast translation from my language)
So, as suggested , the problem was that in Windows' compiler, when you use struct that use function defined in other structs,it is required to pass the .obj file during the compilation .
For doing this you need to compile every .c file that is used by others singulary and then link the .obj file created in this fase.
So in my case the first step is to compile:
cl card.c
that create a card.obj (the Windows' compiler could show you a message that says something like:"The start point is not indicated" if you don't use a main in this first file, don't worry and carry on with this procedure) and then I compile:
cl player.c /link card.obj
So in this way you pass the compiled object in which it's provided the implementation of all the function in the struct.
Related
this a reproducible example and not the entire code the entire code is too large..
my problem was that i had a structure that i created using malloc and i needed to access it from another function in another file, but i keep getting segfault...
header file
main.h
#ifndef main_a
#define main_a
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct cmd_s
{
int n;
} cmd_t;
extern cmd_t *ptr;
void push(char *line);
#endif
the main.c file
main.c
#include "main.h"
cmd_t *ptr = NULL;
int main(void)
{
cmd_t *ptr = malloc(sizeof(cmd_t));
ptr->n = 5;
push("line");
return (0);
}
and where i need to access the struct from named opcode.c
opcode.c
#include "main.h"
void push(char *line)
{
int new = ptr->n;
}
note that this is not the actual code the actual code has useful values, this is an example that contains the challenge i am facing
i tried to use static instead but i got the same error.
i'm still a novice in c programming..
and i don't want to change the way i created the structure, which is through malloc because another function depends on it... i just need to make that malloced structure accessible to another file in the program.
thanks.
int main(void)
{
cmd_t *ptr = malloc(sizeof(cmd_t));
You create new ptr variable visible only in function main. Your push see the global pointer ptr but not the one you have malloced.
You need to
int main(void)
{
ptr = malloc(sizeof(*ptr));
/* .... */
Use obiects not types in sizeof (as in this example)
The struct declaration in my main.c file. I have the function prototype declared but not shown.
typedef struct data
{
int t;
float tp, tf, tt;
} reactorData;
int main()
{
reactorData reactorOne[21];
//other stuff
}
This is the function giving me errors in my function.c file. Specifically in the printf() statement.
typedef struct data reactorData; //this is what I have up top
void reactorOutput(reactorData * data)
{
int c;
for (c=0;c<21;c++)
{
printf(" %3d\t %.0f\t %.0f\t %.0f\n",c, data[c].tp, data[c].tf, data[c].tt);
}
}
The error reads:
|error: invalid use of undefined type 'struct data'|
The function itself works perfectly fine/ I've tested it within main. Its only when I have it in functions.c it doesn't work.
New structs and type definition that must be shared across different compile units are best placed in a header file:
// mystructh.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct data
{
int t;
float tp, tf, tt;
} reactorData;
void reactorOutput(reactorData * data);
// other stuff
#endif
then in the other c files you have to include the header
main.c
#include <stdio.h>
#include "mystruct.h"
int main(void)
{
reactorData reactorOne[21];
// for example
reactorOutput(reactorOne);
//other stuff
}
functions.c
// functions.c
#include "mystruct.h"
void reactorOutput(reactorData * data)
{
int c;
for (c=0;c<21;c++)
{
printf(" %3d\t %.0f\t %.0f\t %.0f\n",c, data[c].tp, data[c].tf, data[c].tt);
}
}
The problem with your version is that struct data is only defined in main.c.
When the compiler compiles functions.c, it doesn't know what struct data is.
That's why you have to use header files live shown above.
I'm programming a queue of my own struct data type in Turbo C++ 3.0, I can't build my project because TC presents me an error message of Undefined symbol when it try to linked it.
I have the following queue.h file
#include <stdio.h>
struct pcb{
int *QueueBase;
char id;
int quantum;
};
typedef struct pcb far * ppcb;
typedef struct nodocola far * pnodocola;
struct nodocola{
ppcb a;
pnodocola ant;
};
void insertProcess(ppcb arg1);
ppcb getProcess();
And my file queue.cpp
#include<stdlib.h>
#include<stdio.h>
#include<cola.h>
struct pcb{
int *QueueBase;
char id;
int quantum;
};
typedef struct pcb far * ppcb;
typedef struct nodocola far * pnodocola;
struct nodocola{
ppcb a;
pnodocola ant;
};
pnodocola base = (pnodocola)malloc(sizeof(pnodocola*));
void insertProcess(ppcb arg1){
base->a = arg1;
pnodocola tmp = (pnodocola)malloc(sizeof(pnodocola*));
tmp = base;
base = (pnodocola)malloc(sizeof(pnodocola*));
base->ant = tmp;
}
ppcb getProcess(){
pnodocola tmp = (pnodocola)malloc(sizeof(pnodocola*));
tmp = base->ant;
base = tmp->ant;
return tmp->a;
}
And the file where I include my file queue.h:
#include<queue.h>
#include<dos.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
void interrupt myTimer(...);
void interrupt (*prev)(...);
ppcb actual = (ppcb)malloc(sizeof(ppcb*));
int ticks;
const quantum = 4;
void main()
{
clrscr();
prev=getvect(8);
setvect(8,myTimer);
getch();
disable();
setvect(8,prev);
enable();
}
void interrupt myTimer(...)
{
(*prev)();
}
void init(...)
{
actual->id='A';
actual->quantum = quantum;
insertProcess(actual);
}
Error: Undefined symbol insertProcess(ppcb far)*
I'm working in a virtual machine with Windows XP 32 bits.
Edit: Sorry I have a mistake, I rename my file from cola.h to queue.h when I write the question, but the #include is correctly and the error is present.
And are you actually linking with the object file produced by queue.cpp? It's not enough to just include the header file in your main code, you have to link both the main code and the queue code when you create the executable.
And, as an aside, why are you using such an archaic C implementation when far better, far more modern and just-as-cheap options are available?
In order to make Turbo C compile multiple source files, I think you have to create a project and then add the C files to that project. It will then know it has to compile and link all those source files in the project.
If you just have a single source file (no project), it treats it as a project with just that file.
You say you include "queue.h" but I can't see a #include "queue.h" anywhere in the relevant file.
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".
File api.h
#include <stdio.h>
#ifndef API
#define API
struct trytag;
typedef struct trytag try;
void trial (try *);
#endif
File core.h
#ifndef CORE
#define CORE
struct trytag
{
int a;
int b;
};
#endif
File func.c
#include "api.h"
#include "core.h"
void trial (try *tryvar)
{
tryvar->a = 1;
tryvar->b = 2;
}
File main.c
#include "api.h"
int main ()
{
try s_tryvar;
trial(&s_tryvar);
printf("a = %d\nb = %d\n", s_tryvar.a, s_tryvar.b);
}
When I compile, I get:
main.c:5: error: storage size of ‘s_tryvar’ isn’t known
If I include core.h in main.c this error doesn't come as try is defined in core.h. But I want the structure try to be hidden to main.c — it should not know the members of try structure. What am I missing?
I don't think what you're trying to do is possible. The compiler needs to know how big a try structure is to compile main.c. If you really want it to be opaque, make a generic pointer type, and instead of declaring the variable directly in main(), make alloc_try() and free_try() functions to handle the creation and deletion.
Something like this:
api.h:
#ifndef API
#define API
struct trytag;
typedef struct trytag try;
try *alloc_try(void);
void free_try(try *);
int try_a(try *);
int try_b(try *);
void trial (try *);
#endif
core.h:
#ifndef CORE
#define CORE
struct trytag
{
int a;
int b;
};
#endif
func.c:
#include "api.h"
#include "core.h"
#include <stdlib.h>
try *alloc_try(void)
{
return malloc(sizeof(struct trytag));
}
void free_try(try *t)
{
free(t);
}
int try_a(try *t)
{
return t->a;
}
int try_b(try *t)
{
return t->b;
}
void trial(try *t)
{
t->a = 1;
t->b = 2;
}
main.c:
#include <stdio.h>
#include "api.h"
int main()
{
try *s_tryvar = alloc_try();
trial(s_tryvar);
printf("a = %d\nb = %d\n", try_a(s_tryvar), try_b(s_tryvar));
free_try(s_tryvar);
}
Think how the opaque FILE structure works in C. You only work with pointers, and you need a function like fopen() to create an instance, and a function like fclose() to dispose of it.
The problem is in main.c, the compiler hasn't seen the definition of struct try. Because of that, the compiler is limited to using pointers to struct try.
What you want to do is add two new functions to your API:
try *create_try();
void *destroy_try(try *t);
These functions will call malloc and free respectively.
If you don't want to limit your structure to only being allowed on the heap, you are going to have to give up on making it opaque.
There is a way to do something that technically is not exactly what you are asking for, but should serve the same purpose of keeping your structure opaque while supporting non-heap allocation.
in api.h, you state an opaque structure as follows:
struct trytag_opaque
{
char data[sizeof(int)*2];
};
if you wanted to be more opaque than that, you could calculate the maximum size of the structure required across any supported platform, and use:
struct trytag_opaque
{
char data[MAX_TRYTAG_SIZE];
};
Then your api.h function declarations would look like:
int try_a(struct trytag_opaque *t)
and your function code would look like:
int try_a(struct trytag_opaque *t_opaque) {
trytag *t = (trytag *)t_opaque;
...
}
and your main.c would look like:
#include "api.h"
int main() {
struct trytag_opaque t;
...
try_a(&t);
...
}