Go Down

Topic: library definition (Read 2028 times) previous topic - next topic

newhobby

Hi,

If I have something like this on my custom library:
Code: [Select]

void TestClass::TestFunction()
{
// Doing Something
#ifdef TESTING
// Do something else
#endif
// Continue doing something
}

Which are the places I could define TESTING, besides TestClass.h or TestClass.cpp?
Could I use a separate .h file on the same folder as INO file?
Could I define somehow inside the INO file?

Thank you,
RI

mromani

* The .h and .cpp files can reside in your "libraries" folder, if they are to be used in more than one sketch, or in the same folder as the .ino file, if they are project-specific.

* The #define TESTING can be placed in the .ino file, before the #include "TestClass.h" statement. If you use the #ifdef TESTING statement consistently across you .h and .cpp files, you can compile a "testing" version or a "production" version of you sketch in no-time by simply commenting out the #define TESTING line atop you .ino file.

newhobby

Doesn't work.
Here is what I have.
Well, it's pde cause I'm still using 0022
TestClass.pde:
Code: [Select]


#define TESTING
#include "TestClass.h"

TestClass  t;

void setup()
{
  Serial.begin(57600);
  Serial.println("Start");
  t.TestFunction();
  Serial.println("End");
}

void loop()
{
}



TestClass.h
Code: [Select]

#ifndef __TESTCLASS_H__
#define __TESTCLASS_H__

#include <TestClass.h>

class TestClass
{
public:
TestClass();
void TestFunction();
};

#endif  // __TESTCLASS_H__


TestClass.cpp
Code: [Select]

#include "TestClass.h"

TestClass::TestClass()
{
}

void TestClass::TestFunction()
{
#ifdef TESTING
Serial.println("Test");
#endif
}


When I comment or uncomment the define on the PDE file, I get no change on the compiled code.
I tried adding new file on the same folder as the PDE called TestH.h:
Code: [Select]

#define TESTING


It still does not do anything.

Any other ideas?

PaulS

Quote
It still does not do anything.

The code does something. Maybe not what you expect/want. But, it does something. What does it do? What do you expect?

One issue with the way that the IDE processes files is that #define can't be the first bit of code in a file. Try adding a dummy variable declaration before the #define in the sketch.

newhobby

In this example, all I wanted to do was to print "Test" if TESTING was defined on either the PDE or in a header file in the same folder as the PDE file:
Code: [Select]

#ifdef TESTING
Serial.println("Test");
#endif


I tried what you recommended and my code turned out to be:
Code: [Select]

byte r;
#define TESTING
#include "TestClass.h"

TestClass  t;

void setup()
{
  Serial.begin(57600);
  Serial.println("Start");
  t.TestFunction();
  Serial.println("End");
}

void loop()
{
}


But it still does not run what's indide the ifdef :(

pYro_65

the #define check is in a .cpp file.
It gets compiled before the pde/ino. Move the function into the header or use the #define in the .h file only.

.h
Code: [Select]

#ifndef __TESTCLASS_H__
#define __TESTCLASS_H__

#include <TestClass.h>

#ifdef TESTING
  #define DEBUG_PRINT( text ) ( Serial.println(text ) )
#else
  #define DEBUG_PRINT( text ) ( (void) 0 )
#endif

class TestClass
{
public:
TestClass();
void TestFunction();
};

#endif  // __TESTCLASS_H__


.cpp
Code: [Select]

#include "TestClass.h"

TestClass::TestClass()
{
}

void TestClass::TestFunction()
{
  DEBUG_PRINT( "Test" );
}


newhobby

I tried your code, but it didn't print "Test".

mromani

Perhaps the function gest "optimized away" ? Just a thought, haven't had the time to test it still...

mromani

Oh, and now that I look closer... you have #include <TestClass.h> in... TestClass.h! ?-|

mromani

Ok, so the problem is this: the .cpp file doesn't #include the sketch, therefore at the time it gets compiled, TESTING is never defined.

The place where to put #define TESTING is therefore TestClass.h, which is included by TestClass.cpp, which in turn will notice if the symbol is defined or not.

Alternatively, you could define TestFunction directly in the .h file, like this:

Code: [Select]
#ifndef _TESTCLASS_H
#define _TESTCLASS_H

#include <Arduino.h>

class TestClass {
public:
    TestClass();
    void TestFunction() {
        #ifdef TESTING
        Serial.println("Test");
        #endif
    };
};


#endif


This way, putting the #define TESTING statements right before the #include "TestClass.h" line works as expected.

newhobby

#10
Jan 12, 2012, 04:38 pm Last Edit: Jan 12, 2012, 05:18 pm by newhobby Reason: 1
I think it worked!!!!
You are a genius!!!
Definitely owe you a beer :)
I'll make some more tests later, gotta go to a meeting atm.
Thank you so much!!!

RI

mromani

Glad to hear that. Thanks for the beer. La berrĂ² alla tua salute ;-)

newhobby

Ok, I've done some tests, but I'm still getting somewhat of a problem.
So, I need to add another level of difficulty.
I have a very complex set of libraries.
The solution provided works if the function is called from withint the INO file itself, but does not work if another library is calling it.
What do I need to do so the define becomes globally visible by all libraries?
Let explain a little of what I'm trying to achieve and maybe you could point me to a better solution.
I have a very large code that I'd like to fit on a UNO board.
If I add all features of the code, it won't fit.
So, I have right now a header file located on Arduino\libraries folder that I can edit and #define which features should be included on the compiled code.
Everything is working really good, except that it makes it really hard to know which features you had uploaded a month ago after you have changed this header file and picked different features.
So, I'm trying to make it so I can pick features within the INO itself and making as simple as possible for the user and at the same time, saving the file would also keep track of which features that code was using.

Here is what my test stuff looks like:
INO file:
Code: [Select]

#define TESTING
#include <TestClass.h>
#include <ParentTestClass.h>

void setup()
{
  Serial.begin(57600);
  //p.DoSomething();
  p.t.TestFunction();
}


void loop()
{
}

In the code above, it works if I call p.t.TestFunction(), but not if I use p.DoSomething().
Even though the DoSomething() function calls the same t.TestFunction()
Here are the supporting libraries:
TestClass.h
Code: [Select]

#ifndef _TESTCLASS_H
#define _TESTCLASS_H

#include <Arduino.h>

class TestClass {
public:
    TestClass();
    byte TestFunction() {
#ifdef TESTING
    Serial.println("Test");
#endif
    };
};


#endif


TestClass.cpp
Code: [Select]

#include "TestClass.h"

TestClass::TestClass()
{
}



ParentTestClass.h
Code: [Select]

#ifndef _PARENTTESTCLASS_H
#define _PARENTTESTCLASS_H

#include <Arduino.h>
#include "TestClass.h"

class ParentTestClass {
public:
TestClass t;
ParentTestClass();
void DoSomething();
};

extern ParentTestClass p;
#endif


ParentTestClass.cpp
Code: [Select]

#include "ParentTestClass.h"

ParentTestClass::ParentTestClass()
{
}

void ParentTestClass::DoSomething()
{
t.TestFunction();
}
ParentTestClass p = ParentTestClass() ;



WizenedEE

What about looking into const global variables? They'll get optimized away no problem, and you'll be able to see them from every file in your project.

newhobby

I think need defs.
I have stuff like this:
Code: [Select]

#if defined FEATURE1
#include <Feature1.h>
#endif  // defined FEATURE1


And this:
Code: [Select]

#ifdef FEATURE1
const prog_char feature1menu_5_label[] PROGMEM = "Feature 1";
#endif  // FEATURE1


And this:
Code: [Select]

#ifdef FEATURE1
case Feature1Menu_Option1:
{
SetupFeature1();
break;
}
#endif  // FEATURE1


So, by just not using one single #define, I can strip a lot of code that won't be used and reduce the code size.
Is there a way to do that with Const too? Could Const be declared inside the INO file and be seem by all libraries?

Go Up