1

I've recently started learning C++ for the STM32F103 microcontroller, and I'm using a library called STM32plus. The problem is, I'm not used to C++ and pointers at all, and this library practically relies on them.

So currently, I have 1 source file where all my code is located, and I want to start splitting it into sections. At the top of my main source file, I have declarations like this:

#include "config/stm32plus.h"
#include "config/display/tft.h"

using namespace stm32plus;
using namespace stm32plus::display;

typedef Fsmc16BitAccessMode<FsmcBank1NorSram1> LcdAccessMode;
typedef SSD1289_Landscape_64K<LcdAccessMode> LcdPanel;

LcdAccessMode *_accessMode;
LcdPanel *dsp;
Font *font;

there's more, but it looks something like that (this section is for the display, there's more for the SD card and other components). I mostly understand what's going on here. One of my functions in this file looks like this:

template <class T>
void print(T text)
{
    textx+=dsp->measureString(text);
    *dsp<<Point(textx,texty)<<text;
}
void println()
{
    textx=0;
    texty+=font->getHeight()+1;
}
template <class T>
void println(T text)
{
    print(text);
    println();
}

Now, I wanted to try and move this into a separate file or class (Print.cpp and Print.h), but after trying all sorts of different things like extern class, including the whole library, forward declarations, and after googling over 10 different errors I got trying to compile that code, and googling what I'm trying to do, I simply cannot find any solution. I would post examples of what I've tried, but I deleted all my previous attempts, and they didn't work at all anyway.

So, can anyone give me an example of a class or way to put these functions in a separate file/class so I can use it in the main program, while still allowing the main program to use display functions?

Any help/advice is appreciated. Note that I'm still new to C++, and that this is an embedded system, so RAM is limited (I can't make another instance of the display objects/classes)

Laurens Weyn
  • 84
  • 1
  • 6
  • Definitions of template classes need to be seen where they're instantiated. You cannot move them into a separate compilation unit. – πάντα ῥεῖ Sep 25 '13 at 09:39
  • @g-makulik I'm not too sure what that means, but I'm guessing you are referring to the 'typedef' lines. I'm pretty sure there's some way to do it though, the author made a really complicated application with multiple files like "LcdManager" and "ImageTransitionAnimator". I would look to see how it's done, but the code is way too advanced and complicated for me to follow.Is there any way to make those template classes acessible to all classes? – Laurens Weyn Sep 25 '13 at 10:27

1 Answers1

1

Regarding the template functions:
At the time you use a template specialisation in a file the definition of the template function needs to be visible. To achieve that you have two possibilities:

  1. You write the definition of the template functions in a header file, and include this header file in all the .cpp files where those functions will be used.

  2. You write a forward declaration of your template function for every type that will be used, that's called a template function specialisation forward declaration (see this thread for the exact syntax).

Regarding the file scope pointers:
If you want your print function to be in print.cpp and use the dsp pointer, you need to make that pointer visible. You could:

1) Add a second parameter to print() of type LCDPanel * (good solution). This way everyone reading the function declaration knows that the function print() uses a LCDPanel and doesn't have to read the function definition to find which global variables are used.

2) Make the LCDPanel pointer global and therefore visible in print.cpp (bad solution):

/* main.cpp */
LcdPanel *dsp; 

/* main.h */
#include "config/stm32plus.h"
#include "config/display/tft.h"

using namespace stm32plus;
using namespace stm32plus::display;

typedef Fsmc16BitAccessMode<FsmcBank1NorSram1> LcdAccessMode;
typedef SSD1289_Landscape_64K<LcdAccessMode> LcdPanel;
extern LCDPanel *dsp;

/* print.cpp */
#include "main.h"

(By the way, dsp is not a great name to designate a display, because dsp is used for Digital Signal Processing in the embedded world)

Community
  • 1
  • 1
Étienne
  • 4,773
  • 2
  • 33
  • 58
  • Thanks! Besides the readability problem, are there any other reasons making LcdPanel global is a bad solution? – Laurens Weyn Sep 25 '13 at 11:43
  • It worked! after some further tweaking (I also had to remove the template things because the linker gave weird errors about the functions not existing) I can finally build my project again! Also, probably going to rename dsp to lcd or something soon – Laurens Weyn Sep 25 '13 at 12:07
  • @LaurensWeyn Glad it helped! For the global variable solution I only meant it was bad because of the readability. – Étienne Sep 25 '13 at 13:46