olikraus / u8g2

U8glib library for monochrome displays, version 2
Other
4.94k stars 1.03k forks source link

Is the U8G2LOG class not wellworking, when used as a inheritable class? #1875

Closed hhuter closed 1 year ago

hhuter commented 2 years ago

Hardware_Pic My dear Oli Krauses and all the other C++ foxes around!

  1. Very THX, Oli, for sharing.
  2. I need some C++ explantions about your lovely u8g2 library

My problems arises, when I derive a class from U8G2LOG

Explanation:

First, this works great and exactly as expected:

// #include <Arduino.h>
#include <U8g2lib.h>

U8G2_SSD1306_128X64_NONAME_2_HW_I2C u8g2(U8G2_R0);

#define U8LOG_W  16
#define U8LOG_H  4
uint8_t u8log_buffer[U8LOG_W*U8LOG_H];

U8G2LOG MyDisp;  // the U8G2LOG objact

void MyDisp_begin() {
  u8g2.begin();                     // use graphic mode
  u8g2.setFont(u8g2_font_t0_16_mr);
  MyDisp.begin(u8g2, U8LOG_W, U8LOG_H, u8log_buffer);  // auto-update
  MyDisp.setLineHeightOffset(3);
  MyDisp.setRedrawMode(0);          // Update screen with every newline 
}

void setup(void) {
  MyDisp_begin();      // Initialisation:     MyDisp
  Serial.begin(9600);  // and the 'classic':  Serial
}

void loop(void) {

  Serial.print("msec:  0x");
  Serial.println(millis(),HEX);  

  /* and now exactly the same on my SSD1306 OLED display: */
  MyDisp.print("msec:  0x");
  MyDisp.println(millis(),HEX);  // Hurra ! The same is displayed

  delay(1000);
}

Next: with the above given 'template' I want to have

// #include <Arduino.h>
#include <U8g2lib.h>

#define U8LOG_W  16
#define U8LOG_H  4

// Plug all U8G2LOG parts into _ONE_ class:
class MYDISP : public U8G2LOG
{
    U8G2_SSD1306_128X64_NONAME_2_HW_I2C  u8g2;  // part: graphic (must done initialised!)
    uint8_t u8log_buffer[U8LOG_W*U8LOG_H];       // part: buffer  (this needs not to be initialized)

  public:
    // this is the constructor (it is a default ctor too):
    MYDISP(const u8g2_cb_t *rotation = U8G2_R0) :
      // initialisation list: doing explizit (the inherited) and the new members constructor(s):
        // U8G2LOG{},     //  inheritance: init. not needed, see u8g2lib.h ... the constructor does nothing
        u8g2{rotation}   //  initialisation of this graphic part member
    {
        u8g2.begin();             // use graphic mode
        u8g2.setFont(u8g2_font_t0_16_mr); 
        this->begin(u8g2b, U8LOG_W, U8LOG_H, u8log_buffer);  // auto-update
        this->setLineHeightOffset(3);    
        this->setRedrawMode(0);    // Update screen with every newline  
    }

    void test() {
      this->println("Hey man");  // even inside this classes objects: the  println()  does not work
    } 
};

// Now testing this class: ===========================================================
//  First: instantiate this class + (plus!) initialise it with (the my prefered) settings:

// MYDISP MyDisp;        // either default constructor,
// MYDISP MyDisp {};     // ... default constructor,
MYDISP MyDisp {U8G2_R0}; // ... or ctor with argument
//  but! this, too (!), makes the Serial monitor disfunctional *) too (?! Why)

void setup(void) {
  Serial.begin(9600);   // for checking the Serial monitor
  // but even this, the Serial is nonfunctial anyfurther, as soon I created my object see *)
}

void loop(void) {

  Serial.print("msec:  0x");    // does no longer work: it does _nothing_ anymore
  Serial.println(millis(),HEX);  

  /* and now exactly the same on my SSD1306 OLED display: */
  MyDisp.print("msec:  0x");    // it displays nothing
  MyDisp.println(millis(),HEX);

  MyDisp.test();                // also this does displays nothing

  delay(1000);
}

Both the above codes should behave exactly identical!

But my 2nd approach:

I already checked the Oli Kraus's source code:

Some explanation would help me to enhance the my C++ language knowledge better, and better, and ...

Thank you very much Johannes

olikraus commented 2 years ago

he did not implement the "print()" functionality directly,

Yes, the code is reused. Otherwise the same code would exist twice in the memory of your controller, wasting flash memory.

but he redirected the arduinos print() function in some way, which my C++ knowledge does not understand.

Not much C++ magic: I just derive from the Arduino print class (if the code is compiled under Arduino environment):

class U8G2LOG
#ifdef ARDUINO
: public Print

Some explanation would help me to enhance the my C++ language knowledge better, and better, and ...

Not sure what other explanation I can give (class inheritance should be explained better in some text books), but I could commend your code a little bit:

The member class initalization expects arguments in inside () not inside {}, so it should be

u8g2(rotation)

instead of

u8g2{rotation}

Below

MYDISP MyDisp {U8G2_R0}; // ... or ctor with argument

Is the same problem: You need to use () instead of {}. In fact using {} will call a not defined default constructor of your class.

There might be another problem: Arduino is not C++. Arduino modifies your C++ so that some things which are required in C++ are not required any more. On the other side some C++ coding styles my not work any more. This not documented, only my personal experience, but it makes working with classes very hard under Arduino.

I personally do not see an issue inside u8g2 here, instead your code looks incorrect to me.

hhuter commented 2 years ago

thx oli kraus i will try your suggestions: .. "change { } enclosurements by ( ) "

... and i will give you the my feedback then.

You, Oli Kraus, you did NOT just simple try and experience the my simplest example codes. You did not really just simply selftrying und experiencing the my code. No compilation error. What is your answer worth - without selfexperiencing the my simple "10 liner" code: -> There is a "logical error" somewhere around - and it is maybe in your library coding?

You suggested: ( ) <--vs--> { } ... My helping C++ learning resource about inheritance and initialisation was this: https://www.learncpp.com/cpp-tutorial/constructors-and-initialization-of-derived-classes/

and no: your speedguessing tip: { } do change it by ( ) did not my simple my code to work.

BUT:

  1. thx oli for sharing your (with your enormous effort taken) and wellwriten code.
  2. i think, it is my problem, to just want to overstress the your code. it's my problem: I am a perfectionist, I am a Nerd, and I have no limit, when how a theme "is best accomplished"
  3. thank you very much, dear oli kraus for your enormous work what you shared with us.

Big THX

PS: what I really want to message to you oli: = = = = = = = = = = = = = = = = = = = = = = is this: ... is Serial monitor defuncting just by C++ using your library?

olikraus commented 2 years ago

Hi There

I am a little bit confused by your last msg, anyhow:

There is a "logical error" somewhere around - and it is maybe in your library coding?

The mentioned curly brackets in your code are wrong. No need to look further here. They need to be replaced. Only once this is fixed, any further debugging would make sense.

And yes, there is a high probability that my lib code still contains bugs.

Oliver

hhuter commented 2 years ago

Hello Oliver,

  1. No, not really: I changed the curly braces against your suggested round braces: --> But the Arduino binary (the "hex-file") are exactly and bitident the same, both: curly (initialisation-list) and rounded (parameter list) compiles to exactly the same nonworking code (as given in the hex-file ) (And clearly as directly uploaded to the Arduino device, it shows the same "nonbehaviour")

  2. You wrote "There might be another problem: Arduino is not C++. Arduino modifies your C++ so that some things which are required in C++ are not required any more. On the other side some C++ coding styles my not work any more. This not documented, only my personal experience, but it makes working with classes very hard under Arduino."

"Arduino is not C++": yes, somehow yes, for example, I see this

But still I think it is a more or less a transparent GCC toolchain with a more or less "pure" C++ ?

Thx a lot for your guidance and the hints. Have a good week. Johannes

olikraus commented 2 years ago

But still I think it is a more or less a transparent GCC toolchain with a more or less "pure" C++ ?

Arduino applies a preprocessing step. The generted cpp file should be there in the build folder.

hhuter commented 2 years ago

thx oliver,

i will stay on this your debugging hint. sometimes the next days or weeks. or so. it is not an urgent problem. and - it is just a beautifing elegance problem.

liebe grüsse nach deutschland von johannes aus österreich

! is there any other c++ gcc arduino nerd here? hello world ! where are you ?