Page 1 of 2

Bit of help making struct global.

Posted: Sat Jan 07, 2012 7:18 am
by jdal
I could use your help in making the following struct global.
I have several *.cpp files in my project and i want all of them to have access to this struct.
I have tried everything i can think of but with no success.

#define STRING_SIZE (512)
#define PATTERNS (1024)


struct zdata
{
char string_x[STRING_SIZE];
char string_y[STRING_SIZE];

}final_data[PATTERNS];


for my usage i am doing

strncpy(final_data[x].string_x,string_data_x, strlen(string_data_x));
strncpy(final_data[x].string_x,string_data_y, strlen(string_data_y));

Re: Bit of help making struct global.

Posted: Mon Jan 09, 2012 11:26 am
by tod
Look up the extern keyword.

Re: Bit of help making struct global.

Posted: Mon Jan 09, 2012 11:31 am
by jdal
Yes, i know about extern, however when it comes to structs its not that simple anymore.
Not to mention some people place the struct in the .C file and others place it in the header file.

Re: Bit of help making struct global.

Posted: Mon Jan 09, 2012 11:47 am
by rsg
In a header file (for example, zdata.h), do something like the following to declare the struct's type and the global variable itself:

Code: Select all

#ifndef ZDATA_H
#define ZDATA_H

#define STRING_SIZE (512)
#define PATTERNS (1024)

// Declare the type of the global struct
// (You don't need to use typedef to make this work,  but I would suggest you do...)
typedef struct
{
  char string_x[STRING_SIZE];
  char string_y[STRING_SIZE];
} zdata_t;

// Declare the global struct - i.e. the actual instance
extern zdata_t final_data[PATTERNS];
. . .
#endif
Then, in a .c file (e.g. zdata.c), do something like this to define (aka implement) the actual variable:

Code: Select all

#include "zdata.h"

// Define the global struct - this is the actual instance
zdata_t final_data[PATTERNS];
. . .
Similarly, other files that need to access the struct can do this:

Code: Select all

. . .
#include "zdata.h"
. . .
void someFunc()
{
  printf("Hello %s\n", final_data[0].string_x);
}
Do note the usual problems and precautions with global variables; generally, you don't want to do it!

Regards...

Re: Bit of help making struct global.

Posted: Mon Jan 09, 2012 12:08 pm
by jdal
I have tried many iterations like that, but the one you sent worked.
Thank you so much for the excellent example!!!

Do note the usual problems and precautions with global variables; generally, you don't want to do it!
I have about 8 tasks in this project. I like to keep each task in its own .cpp file so its easy to locate in the directory tree.
3 of these tasks need access to this data which is why i wanted to make it a global variable. Should i be doing it in a different way ?

Re: Bit of help making struct global.

Posted: Mon Jan 09, 2012 12:32 pm
by rsg
Glad that helped.

You usually don't want to have shared/global variables because it gets very difficult to manage who/when it get written or read, especially if you have multiple tasks, and even worse, interrupt service routines. Truly global structs, like in my example, may be written by any piece of code that includes zdata.h. As the size of your app gets larger, with more files, it gets harder to keep track of where and when the data gets written.

Even more difficult, even if you only have one writer, you likely will run into situations where, while one task is reading the shared information, another may change it; the reader may get an inconsistent picture. Say you have something simple such as a mouse, and your writer is an interrupt service routine that receives an x and a y coordinate. If you store these in an unprotected shared memory struct, you may get the following situation

1. ISR occurs, writes X0 and Y0
2. Task reads X0
3. ISR occurs, writes X1 and Y1
4. Task resumes, reads Y1

At the end of this sequence, you see that Task will be operating on point [X0, Y1], which is just not right. There are many, many more ways that this problem can sink your ship.

There are many other ways to solve this problem (coding conventions, accessor functions, message-passing, etc.) with varying degrees of protection against these unfettered access and inconsistent state problems. Without knowing much more about your app, it isn't reasonable to make specific recommendations (hence, I just answered your question, because maybe that is the best approach for your specific app), but you may want to do a little research on encapsulation, data hiding, modular design, singletons, and the like.

Regards...

Re: Bit of help making struct global.

Posted: Mon Jan 09, 2012 12:49 pm
by jdal
Thank you for the information. I have wrote it carefully so that any situation like that will not arise.

Re: Bit of help making struct global.

Posted: Mon Jan 09, 2012 12:51 pm
by tod
Should i be doing it in a different way ?
Probably. Are you familiar with the concepts of mutual exclusion? That is are you preventing one task from writing to this data while another task is in the middle of reading it? My opinion is that by the time you properly protect global memory access from multiple tasks (semaphores or enabling/disabling scheduling) you're better off using the tools provided by the UCOS: mailboxes, queues, fifos etc. They pass pointers but most of the mechanisms include some form of baked-in mutual exclusion. You can read the uCOSLibrary.pdf but it's more of a reference. I found LaBrosse's book much more helpful when initially learning this, maybe someone else has URL's or other resources for mastering multi-process programming.

Re: Bit of help making struct global.

Posted: Mon Jan 09, 2012 12:55 pm
by rsg
Yes, tod, add that to my list - how could I have forgotten?! :oops: But seriously, excellent advise...

Re: Bit of help making struct global.

Posted: Mon Jan 09, 2012 1:08 pm
by jdal
In this particular situation, one thread is collecting data. when this same task gets to the size limit it stops.
the other task reads the data, yet its only allowed to read 1 less than the collecting task has stored.
Moreover, the reading task is pending on a sem. so it only gets fired when the reader updates the next new value.

I will look more into what you guys are talking about.