Arduino library dev problem!

Hi
I wanted to use a little cpp source code in an arduino sketch, but it used the stack library from STL, so i decided to make my own just like it. Following the libraries tutorial on the arduino website i put together this:

Stack.h:

#ifndef STACK_H
#define STACK_H

template <class T>
class Stack {

    public:

        //Constructor
        Stack ();

        //Destructor
        ~Stack ();

        //Add an item to the stack
        void push (T item);

        //See the top item of the stack
        T top ();

        //Remove the top item of the stack
        void pop ();

        //Check if the stack is empty
        bool empty();

    private:

        struct element
        {
            T value;
            element *next;
        };

        struct main
        {
            int elements;
            element *top;
        };

        main * _main;
        element * _new, * _old;

        void deleteStack (element * el, int i);

};

#endif // STACK_H

Stack.cpp:

#include <Stack.h>

template <typename T>
Stack<T>::Stack ()
{
    _main = new main;
    _main.elements = 0;
}

template<typename T>
void Stack<T>::deleteStack (element * el, int i)
{
    if(i) deleteStack ( el.next , i-1 );
    delete el;
}

template<typename T>
Stack<T>::~Stack ()
{
    deleteStack ( _main.top, _main.elements-1 );
    delete _main;
}

template <typename T>
void Stack<T>::push(T item)
{
    _new = new element;
    _new.value = item;
    _new.next = _main.top;
    _main.top = _new;
}

template <typename T>
T Stack<T>::top()
{
    return _main.top.value;
}

template <typename T>
void Stack<T>::pop()
{
    _old =_main.top;
    _main.top = _main.top.next;
    delete _old;
}

template <typename T>
bool Stack<T>::empty()
{
    if(!_main.elements)return false;
    else return true;
}

But it didnt exactly work! i think that it is because of the template thing but i dont know. The arduino IDE said this:

stack.cpp.o: In function `__static_initialization_and_destruction_0':
C:\Users\Moni\AppData\Local\Temp\build4110618608836428356.tmp/stack.cpp:5: undefined reference to `Stack<int>::Stack()'
C:\Users\Moni\AppData\Local\Temp\build4110618608836428356.tmp/stack.cpp:5: undefined reference to `Stack<int>::~Stack()'
stack.cpp.o: In function `setup':
C:\Users\Moni\AppData\Local\Temp\build4110618608836428356.tmp/stack.cpp:9: undefined reference to `Stack<int>::push(int)'
C:\Users\Moni\AppData\Local\Temp\build4110618608836428356.tmp/stack.cpp:10: undefined reference to `Stack<int>::top()'
C:\Users\Moni\AppData\Local\Temp\build4110618608836428356.tmp/stack.cpp:11: undefined reference to `Stack<int>::pop()'
C:\Users\Moni\AppData\Local\Temp\build4110618608836428356.tmp/stack.cpp:12: undefined reference to `Stack<int>::empty()'

Please help me! I really want to make this work !! Thanks in advanced :slight_smile: :slight_smile: :slight_smile: :smiley: :smiley: :smiley:

Can you post your testcode?

Seems to be a linker problem. The IDE did not find the Stack.cpp object code. In my own project I usually create a "utility" folder which contains my additional code. The utility folder seems to be analysed by the Arduino IDE. Indeed to me it is still an open question which are the search pathes of the Arduino IDE.

Oliver

My guess is that you're running into this problem:
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12

I had never considered this; I've always included definitions inline in my templates.

This is the test code;

#include <Stack.h>
Stack <int> st;

void setup ()
{
  st.push(5);
  int a = st.top();
  st.pop();
  bool b = st.empty();
}

void loop ()
{
  
}

All the files are in their proper places and are properly named. I also took a look at Templates, C++ FAQ and tried a few things but they didn`t work. Any more ideas?

If you take the .h file from your original post, and add the function implementations that you have in the cpp file to make each function inline, you're almost there. e.g.

template <class T>
class Stack {

    public:

        //Constructor
        Stack ()
        {
          _main = new main;
          _main.elements = 0;
        }

Now, replace all of the periods with ->, because the data members you're addressing are pointers

        //Constructor
        Stack ()
        {
          _main = new main;
          _main->elements = 0;
        }

Now, you'll need an implementation of new and delete; you can add them at the end of your sketch

void * operator new( size_t size ) { return malloc( size ); } 
void operator delete( void * ptr ) { if ( ptr ) free( ptr ); }

Now, it will compile and link. If you have problems, try creating a new sketch and pasting the following, which is the new header file as described above, plus your test code from your most recent post and the new and delete implementations, all in one file.

void * operator new( size_t size ) { return malloc( size ); } 
void operator delete( void * ptr ) { if ( ptr ) free( ptr ); } 

template <class T>
class Stack {

    public:

        //Constructor
        Stack ()
        {
          _main = new main;
          _main->elements = 0;
        }

        //Destructor
        ~Stack ()
        {
          deleteStack ( _main->top, _main->elements-1 );
          delete _main;
        }

        //Add an item to the stack
        void push (T item)
        {
          _new = new element;
          _new->value = item;
          _new->next = _main->top;
          _main->top = _new;
        }

        //See the top item of the stack
        T top ()
        {
            return _main->top->value;
        }

        //Remove the top item of the stack
        void pop ()
        {
            _old =_main->top;
            _main->top = _main->top->next;
            delete _old;
        }

        //Check if the stack is empty
        bool empty()
        {
            if(!_main->elements)return false;
            else return true;
        }

    private:
        struct element
        {
            T value;
            element *next;
        };

        struct main
        {
            int elements;
            element *top;
        };

        main * _main;
        element * _new, * _old;


        void deleteStack (element * el, int i)
        {
          if(i) deleteStack ( el->next , i-1 );
          delete el;
        }

};

Stack <int> st;

void setup ()
{
  st.push(5);
  int a = st.top();
  st.pop();
  bool b = st.empty();
}

void loop ()
{
  
}

Good luck!

Hi, kerthyn,
Thanks for the help! I did as told me but it still doesn`t work this the header file, i think i got everything right.

#ifndef STACK_H
#define STACK_H

void * operator new( size_t size ) { return malloc( size ); }
void operator delete( void * ptr ) { if ( ptr ) free( ptr ); }

template <class T>
class Stack {

    public:

        //Constructor
        Stack ()
        {
            _main = new main;
            _main->elements = 0;
        }

        //Destructor
        ~Stack ()
        {
            deleteStack ( _main->top, _main->elements-1 );
            delete _main;
        }

        //Add an item to the stack
        void push (T item)
        {
            _new = new element;
            _new->value = item;
            _new->next = _main->top;
            _main->top = _new;
        }

        //See the top item of the stack
        T top ()
        {
            return _main->top->value;
        }

        //Remove the top item of the stack
        void pop ()
        {
            _old =_main->top;
            _main->top = _main->top->next;
            delete _old;
        }

        //Check if the stack is empty
        bool empty()
        {
            if(!_main->elements)return false;
            else return true;
        }

    private:

        struct element
        {
            T value;
            element *next;
        };

        struct main
        {
            int elements;
            element *top;
        };

        main * _main;
        element * _new, * _old;

        void deleteStack (element * el, int i)
        {
            if(i) deleteStack ( el.next , i-1 );
            delete el;
        }
};

#endif // STACK_H

And these are the cimpiller errors:

In file included from stack.cpp:1:
C:\Program Files (x86)\Arduino\libraries\Stack/Stack.h:4: error: declaration of 'operator new' as non-function
C:\Program Files (x86)\Arduino\libraries\Stack/Stack.h:4: error: 'size_t' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\Stack/Stack.h: In function 'void operator delete(void*)':
C:\Program Files (x86)\Arduino\libraries\Stack/Stack.h:5: error: 'free' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\Stack/Stack.h: In member function 'void Stack<T>::deleteStack(Stack<T>::element*, int) [with T = int]':
C:\Program Files (x86)\Arduino\libraries\Stack/Stack.h:22:   instantiated from 'Stack<T>::~Stack() [with T = int]'
stack.cpp:5:   instantiated from here
C:\Program Files (x86)\Arduino\libraries\Stack/Stack.h:75: error: request for member 'next' in 'el', which is of non-class type 'Stack<int>::element*'

Any thoughts ???

Nearly there!

There's no need for a stack.cpp; everything you need is in stack.h. Just delete stack.cpp from your sketch folder (keep a copy somewhere.) If you include stack.h in your main sketch file (or in whatever file needs stack<>), all should be well, except...

The new and delete functions should be defined only once (i.e. the implementation should only appear in one place.) You can put these in a separate file in your sketch folder (and the IDE will append that file to your sketch file before compilation,) or you can simply add them somewhere in your main sketch. You shouldn't need to declare these functions in your .h file, so remove those lines:

#ifndef STACK_H
#define STACK_H

// remove these next two lines
//void * operator new( size_t size ) { return malloc( size ); }
//void operator delete( void * ptr ) { if ( ptr ) free( ptr ); }

template <class T>
...

When i put new and delete in the sketch it compiles, but not when they are in a file. BTW should i put anything else in that file or leave it just as it is? :

void * operator new( size_t size ) { return malloc( size ); }
void operator delete( void * ptr ) { if ( ptr ) free( ptr ); }

The iterations towards fixing this are unlikely to be of interest to others; check you private messages. When it's all working you can post the solution, which might be useful to others.

Well finally this is the first working version: v1.0
with the help of Arduino forum user: kerthyn
You can download it from the bottom of the post!

 Directory of c:\Program Files (x86)\Arduino\libraries\Stack

09.08.2011 ?.  16:52    <DIR>          .
09.08.2011 ?.  16:52    <DIR>          ..
09.08.2011 ?.  16:49               453 CppSupport.cpp
09.08.2011 ?.  16:48               583 CppSupport.h
10.08.2011 ?.  10:18    <DIR>          Examples
09.08.2011 ?.  16:52                94 keywords.txt
09.08.2011 ?.  16:51             1 738 Stack.h
               4 File(s)          2 868 bytes

Stack.h:

/*
Stack - library supporting the stack container.

Written by Simeon Dorelov
Date: 9 August 2011
*/

#ifndef STACK_H
#define STACK_H

#include <CppSupport.h>

template <class T>
class Stack {

    public:

        //Constructor
        Stack ()
        {
            _main = new main;
            _main->elements = 0;
        }

        //Destructor
        ~Stack ()
        {
            deleteStack ( _main->top, _main->elements-1 );
            delete _main;
        }

        //Add an item to the stack
        void push (T item)
        {
            _new = new element;
            _new->value = item;
            _new->next = _main->top;
            _main->top = _new;
            _main->elements++;
        }

        //See the top item of the stack
        T top ()
        {
            return _main->top->value;
        }

        //Remove the top item of the stack
        void pop ()
        {
            _old =_main->top;
            _main->top = _main->top->next;
            delete _old;
            _main->elements--;
        }

        //Check if the stack is empty
        bool empty()
        {
            if(!_main->elements)return true;
            else return false;
        }

        //Check the number of elements in the stack
        int size ()
        {
            return _main->elements;
        }

    private:

        struct element
        {
            T value;
            element *next;
        };

        struct main
        {
            int elements;
            element *top;
        };

        main * _main;
        element * _new, * _old;

        void deleteStack (element * el, int i)
        {
            if(i) deleteStack ( el->next , i-1 );
            delete el;
        }
};

#endif // STACK_H

CppSupport.h:

#ifndef CPPSUPPORT_H_INCLUDED
#define CPPSUPPORT_H_INCLUDED
#include <stdlib.h>
#ifdef __cplusplus
void * operator new( size_t size );
void operator delete( void * ptr );
extern "C"
{
#endif
  typedef int __guard __attribute__((mode (__DI__)));

  int __cxa_guard_acquire(__guard *);
  void __cxa_guard_release (__guard *);
  void __cxa_guard_abort (__guard *);
  int atexit(void (*)(void));    // support static objects
  void __cxa_pure_virtual(void); // support pure virtual classes
#ifdef __cplusplus
}  // extern "C"
#endif

#endif // CPPSUPPORT_H_INCLUDED

CppSupport.cpp

#include <stdlib.h>
#include "CppSupport.h"

void * operator new( size_t size ) { return malloc( size ); }
void operator delete( void * ptr ) { if ( ptr ) free( ptr ); }

extern "C"
{
  int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
  void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
  void __cxa_guard_abort (__guard *) {};
  int atexit(void (*)(void)) {return 0;}
  void __cxa_pure_virtual(void) {};
}  // extern "C"

keywords.txt

Stack	KEYWORD1
CppSupport	KEYWORD1
top	KEYWORD2
push	KEYWORD2
pop	KEYWORD2
empty	KEYWORD2

Examples\ReverseSerial\ReverseSerial.pde:

#include <Stack.h>

Stack <char> st;


void setup ()
{
  Serial.begin(9600);
}

void loop ()
{
  if(Serial.available())
  {
    while(Serial.available())
      st.push(Serial.read());
    while(!st.empty())
    {
      Serial.print(st.top());
      st.pop();
    }
    Serial.println();
  }
}

Stack.rar (1.86 KB)