How to make a "global" array that's accessible in classes?

Hello,

I have a very "object oriented" codebase that I'm working on. In that code, I need to share an array containing 256 integers among various classes. I know that I can pass a pointer to that array into the class constructors, but is there any possible way to make that array "global"?

So, for example, I might define the array as:

uint16_t mebob[256] = { 45, 233, ... };

And I'd love to access it in my classes like:

void MyClass::doSomething()
{
uint16_t ardvill;
ardvill = mebob[2];
}

I know it's not great practice, but in this particular case, it would be very convenient.

Thanks,
Bret

One way would be to pass a pointer to the array as a parameter to the object's constructor.

Or, as a parameter to the class function when you invoke it.

I think you can use the extern keyword to say to your class that you will use a global variable that is declared in another header file.
Although I'm not sure if it will be valid inside the class.Keep in mind that "global variable" is a little dangerous since you can loose track of who is changing the array in a real big project and could be a pain in the ass to debug problems with the array.

What happens if you create the array before you #include the library with the class?

...R

Another important question is to ask yourself why it needs to be global. There's a difference between having all elements of a system having access to the array and having the global storage class.

clone45:
is there any possible way to make that array "global"?

Accessing global data within a class is no different to accessing global data anywhere else. Make the definition global (i.e. outside of any functions, methods or classes) and then declare it either directly within your class's implementation or indirectly via a file that is #included within your class's implementation. (If you need more than one compilation unit to access the global data then it would be good practice to put the declaration in a header file that could be #included in both compilation units, to avoid duplicating the declaration.)

Thanks for all of the replies. Can someone show me some sample code on how to pull it off? My actual array holds a sin table, so it's set-in-stone.

Cheers,
Bret

Can I take a stab and guess that you are declaring the array in your sketch and trying to access it directly by name in your library?

Its not going to work this way as the library is compiled before your sketch is seen! You need to do as people have mentioned and pass into the class a pointer or reference to the array. Or have a global pointer that you can set in your library .h.

clone45:
Thanks for all of the replies. Can someone show me some sample code on how to pull it off? My actual array holds a sin table, so it's set-in-stone.

Cheers,
Bret

It would look roughly like this - really no different to accessing external data in any other situation:

int foo = 1;
extern int foo;
#include "foo.h"
void myclass::mymethod()
{
    int x = foo;
    etc
}

Replace foo with your array name, length etc as required.

Peter, your example really helped out. Thanks a ton.

Is it possible to have extern objects? I have a class for doing fixed-point math which contains a few large arrays. It would be great to make this class available to other classes without taking up tons of memory.

Cheers,
Bret

Put the array in progmem, then no code can change it.
I make all my variables global - declare them after the #defines & #includes and before void setup(),
lets any code access it from anywhere. All you software guys can say how bad it is, but it works for me.

@CrossRoads: That sounds like a perfectly good approach, but I'm using the Due, and I don't think that it supports progmem. I've tried to make my extern variables 'const' so that they might be put into the program memory, but I ran into compilation issues. I might try that again soon.

@Peter: Do you have any example of declaring an instance of a class extern?

Thanks,
Bret

clone45:
@Peter: Do you have any example of declaring an instance of a class extern?

It's the same as declaring and defining a variable of any other type. Just replace 'int' with the class in that example, and then change the definition of the instance to use the appropriate constructor. The code referencing the class instance would need to have visibility of the class declaration, which you'd usually do by #including a .h file that declared the class.

Due doesn't do progmem?
Man, I am sticking with the 8-bit stuff.

Here's an approach I have used in pure C programs:
Create a file math_tables.c ---

#define MATH_TABLES
#include "math_tables.h"

/* don't conflict with system's sin() function */
const float mysin[] = {0.0, 0.1, 0.2, /* ... */ 0.99 };

Then set up a header file math_tables.h ---

#ifdef MATH_TABLES
  const float mysin[]; /* don't conflict with system's sin() function */
#else
  extern const float mysin[];
#endif

Finally, use it like this:

#include <stdio.h>
#include "math_tables.h"

class mystuff {
public:
    float bar(int i) {
        return mysin[i];
    }
};

void bar(void) {
    mystuff ms;
    printf("%f\n", ms.bar(3));
}

Hi Bobmon,

I tried exactly as you recommended, but got an error. Here's my code:

In FixedPointMathTables.cpp:

#define FIXED_POINT_MATH_TABLES
#include "FixedPointMathTables.h"

const uint16_t fixed_point_sin[] = { 0,3,6,9,12,15,18,21,25,28,... };
const uint16_t fixed_point_exp[] = { 4095,4087,4079,4071,4063,... };

In FixedPointMathTables.h:

#include "Arduino.h"

#ifdef FIXED_POINT_MATH_TABLES
  const uint16_t fixed_point_sin[];
  const uint16_t fixed_point_exp[];
#else
  extern const uint16_t fixed_point_sin[];
  extern const uint16_t fixed_point_exp[];  
#endif

In usage:

#include "FixedPointMathTables.h"

uint32_t FixedPointMath::sin_fix1212(uint32_t in)
{
  uint32_t out = 0;
  uint16_t x = in % 4096;
  if(x>=0 && x<1024) out = fixed_point_sin[x]+0x0800;
  if(x>=1024 && x<2048) out = fixed_point_sin[2047-x]+0x0800;
  if(x>=2048 && x<3072) out = -fixed_point_sin[x-2048]+0x0800;
  if(x>=3072 && x<4096) out = -fixed_point_sin[4095-x]+0x0800;
  if (out>=4095) out = 4095;
  return out;
}

And the error message was:

In file included from FixedPointMathTables.cpp:2:
FixedPointMathTables.h:4: error: uninitialized const 'fixed_point_sin'
FixedPointMathTables.h:4: error: storage size of 'fixed_point_sin' isn't known
FixedPointMathTables.h:5: error: uninitialized const 'fixed_point_exp'
FixedPointMathTables.h:5: error: storage size of 'fixed_point_exp' isn't known

Any suggestions?

Oh! I got it to work. I'm not sure if this is going to cause problems later, but I changed FixedPointMathTables.h to:

#include "Arduino.h"

#ifndef FIXED_POINT_MATH_TABLES
  extern const uint16_t fixed_point_sin[];
  extern const uint16_t fixed_point_exp[];  
#endif

Cheers,
Bret

bobmon:
Then set up a header file math_tables.h ---

#ifdef MATH_TABLES

const float mysin[]; /* don't conflict with system's sin() function */
#else
  extern const float mysin[];
#endif

I don't understand how that would work. What is the point of the non-extern declaration of mysin? And what is the conflict that this declaration is intended to avoid? It seems to me that you just need an extern declaration in the header file, and a definition with initialisation in the cpp file. It's common to use a #ifdef per header file to prevent duplicated inclusions within a given compilation unit, and perhaps that's what this has evolved from, but what you're doing here is not at all conventional.