[Solved]The right way of getting a variable from an existing library

I have a seemingly simple question for probably c++ in general.

I am working with the Nextion library (https://github.com/itead/ITEADLIB_Arduino_Nextion)

there is a file called NexHardware.cpp and in that file, I have expanded the nexLoop function to retrieve a page number for me.

What is the appropriate way to get the value of that variable into my main sketch?

EDIT: rereading what I wrote didnt make any sense, so here is the code (look at the very bottom):

NexHardware.cpp:

/**
 * @file NexHardware.cpp
 *
 * The implementation of base API for using Nextion. 
 *
 * @author  Wu Pengfei (email:<pengfei.wu@itead.cc>)
 * @date    2015/8/11
 * @copyright 
 * Copyright (C) 2014-2015 ITEAD Intelligent Systems Co., Ltd. \n
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 */
#include "NexHardware.h"

#define NEX_RET_CMD_FINISHED (0x01)
#define NEX_RET_EVENT_LAUNCHED (0x88)
#define NEX_RET_EVENT_UPGRADED (0x89)
#define NEX_RET_EVENT_TOUCH_HEAD (0x65)
#define NEX_RET_CURRENT_PAGE_ID_HEAD (0x66)
#define NEX_RET_EVENT_POSITION_HEAD (0x67)
#define NEX_RET_EVENT_SLEEP_POSITION_HEAD (0x68)
#define NEX_RET_STRING_HEAD (0x70)
#define NEX_RET_NUMBER_HEAD (0x71)
#define NEX_RET_INVALID_CMD (0x00)
#define NEX_RET_INVALID_COMPONENT_ID (0x02)
#define NEX_RET_INVALID_PAGE_ID (0x03)
#define NEX_RET_INVALID_PICTURE_ID (0x04)
#define NEX_RET_INVALID_FONT_ID (0x05)
#define NEX_RET_INVALID_BAUD (0x11)
#define NEX_RET_INVALID_VARIABLE (0x1A)
#define NEX_RET_INVALID_OPERATION (0x1B)

/*
 * Receive uint32_t data. 
 * 
 * @param number - save uint32_t data. 
 * @param timeout - set timeout time. 
 *
 * @retval true - success. 
 * @retval false - failed.
 *
 */
bool recvRetNumber(uint32_t *number, uint32_t timeout)
{
    bool ret = false;
    uint8_t temp[8] = {0};

    if (!number)
    {
        goto __return;
    }

    nexSerial.setTimeout(timeout);
    if (sizeof(temp) != nexSerial.readBytes((char *)temp, sizeof(temp)))
    {
        goto __return;
    }

    if (temp[0] == NEX_RET_NUMBER_HEAD && temp[5] == 0xFF && temp[6] == 0xFF && temp[7] == 0xFF)
    {
        *number = ((uint32_t)temp[4] << 24) | ((uint32_t)temp[3] << 16) | (temp[2] << 8) | (temp[1]);
        ret = true;
    }

__return:

    if (ret)
    {
        dbSerialPrint("recvRetNumber :");
        dbSerialPrintln(*number);
    }
    else
    {
        dbSerialPrintln("recvRetNumber err");
    }

    return ret;
}

/*
 * Receive string data. 
 * 
 * @param buffer - save string data. 
 * @param len - string buffer length. 
 * @param timeout - set timeout time. 
 *
 * @return the length of string buffer.
 *
 */
uint16_t recvRetString(char *buffer, uint16_t len, uint32_t timeout)
{
    uint16_t ret = 0;
    bool str_start_flag = false;
    uint8_t cnt_0xff = 0;
    String temp = String("");
    uint8_t c = 0;
    long start;

    if (!buffer || len == 0)
    {
        goto __return;
    }

    start = millis();
    while (millis() - start <= timeout)
    {
        while (nexSerial.available())
        {
            c = nexSerial.read();
            if (str_start_flag)
            {
                if (0xFF == c)
                {
                    cnt_0xff++;
                    if (cnt_0xff >= 3)
                    {
                        break;
                    }
                }
                else
                {
                    temp += (char)c;
                }
            }
            else if (NEX_RET_STRING_HEAD == c)
            {
                str_start_flag = true;
            }
        }

        if (cnt_0xff >= 3)
        {
            break;
        }
    }

    ret = temp.length();
    ret = ret > len ? len : ret;
    strncpy(buffer, temp.c_str(), ret);

__return:

    dbSerialPrint("recvRetString[");
    dbSerialPrint(temp.length());
    dbSerialPrint(",");
    dbSerialPrint(temp);
    dbSerialPrintln("]");

    return ret;
}

/*
 * Send command to Nextion.
 *
 * @param cmd - the string of command.
 */
void sendCommand(const char *cmd)
{
    while (nexSerial.available())
    {
        nexSerial.read();
    }

    nexSerial.print(cmd);
    nexSerial.write(0xFF);
    nexSerial.write(0xFF);
    nexSerial.write(0xFF);
}

/*
 * Command is executed successfully. 
 *
 * @param timeout - set timeout time.
 *
 * @retval true - success.
 * @retval false - failed. 
 *
 */
bool recvRetCommandFinished(uint32_t timeout)
{
    bool ret = false;
    uint8_t temp[4] = {0};

    nexSerial.setTimeout(timeout);
    if (sizeof(temp) != nexSerial.readBytes((char *)temp, sizeof(temp)))
    {
        ret = false;
    }

    if (temp[0] == NEX_RET_CMD_FINISHED && temp[1] == 0xFF && temp[2] == 0xFF && temp[3] == 0xFF)
    {
        ret = true;
    }

    if (ret)
    {
        dbSerialPrintln("recvRetCommandFinished ok");
    }
    else
    {
        dbSerialPrintln("recvRetCommandFinished err");
    }

    return ret;
}

bool nexInit(void)
{
    bool ret1 = false;
    bool ret2 = false;

    //dbSerialBegin(115200);
    //nexSerial.begin(115200);
    sendCommand("");
    sendCommand("bkcmd=1");
    ret1 = recvRetCommandFinished();
    sendCommand("page 0");
    ret2 = recvRetCommandFinished();
    return ret1 && ret2;
}

void nexLoop(NexTouch *nex_listen_list[])
{
    static uint8_t __buffer[10];

    uint16_t i;
    uint8_t c;

    while (nexSerial.available() > 0)
    {
        delay(10);
        c = nexSerial.read();

        if (NEX_RET_EVENT_TOUCH_HEAD == c)
        {
            if (nexSerial.available() >= 6)
            {
                __buffer[0] = c;
                for (i = 1; i < 7; i++)
                {
                    __buffer[i] = nexSerial.read();
                }
                __buffer[i] = 0x00;

                if (0xFF == __buffer[4] && 0xFF == __buffer[5] && 0xFF == __buffer[6])
                {
                    NexTouch::iterate(nex_listen_list, __buffer[1], __buffer[2], (int32_t)__buffer[3]);
                }
            }
        }
        if (NEX_RET_CURRENT_PAGE_ID_HEAD == c)
        {
            if (nexSerial.available() >= 4)
            {
                __buffer[0] = c;
                for (i = 1; i < 5; i++)
                {
                    __buffer[i] = nexSerial.read();
                }
                __buffer[i] = 0x00;

                if (0xFF == __buffer[2] && 0xFF == __buffer[3] && 0xFF == __buffer[4])
                {
                    //Here is where I need to get this into a global variable
                    //something = __buffer[1];
                }
            }
        }
    }
}

So, in NexHardware.h i declared:

extern int pageDisplayed;

and in NexHardware.cpp I declared:

int pageDisplayed = 0;

(Then it will get assigned once that function runs)

and in my sketch, I commented out the declaration, but still use the variable where I need. Is that the way to do it?

theskaz:
Is that the way to do it?

No, it's not. Two cornerstones of Object Oriented Programming are encapsulation and abstraction. Your method violates both.

You should keep the value you need to make available in its own private variable within the class. Then, you provide a public class method that will return the value of that private variable. Call that method from your main sketch.

gfvalvo:
No, it's not. Two cornerstones of Object Oriented Programming are encapsulation and abstraction. Your method violates both.

You should keep the value you need to make available in its own private variable within the class. Then, you provide a public class method that will return the value of that private variable. Call that method from your main sketch.

I get that, in general.

in c# I would create a private variable, pass it to a public property and the calling class would access the property after instantiating the class.

my C++ isnt that strong, but I believe that the author of this library isnt creating a class. within the function that I modified there is a call to a static function NexTouch:iterate, but other than that, there seems to be no indication of a class here. I dont think i am strong enough in c++ to convert this into a class without breaking everything else.

in my loop(), I just call nexLoop(nex_listen_list); I dont instantiate a class, or call it as a static function or anything. This is where I get confused.

Sorry, should have looked at the code more carefully. I just saw "library" and assumed it defined a C++ class.

Anyway, you can achieve similar abstraction using just C techniques. Store your desired value to a global variable (defined at top of file and not inside a function), but make it static:

static uint8_t something;

Then, create a new function that returns that value:

uint8_t getSomething() {
  return something;
}

By making it 'static' you restrict its scope to NexHardware.cpp, it can't be accessed from any other file. But, the getSomething() function can return it because you create it in the same file.

Thank you!

I did that, and added to NexHardware.h:

uint8_t getSomething();

mainly because that seems to fit the pattern.

It does the trick, and I learned something new.