Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to set environment variables properly



  • Hello everyone,

    I would like to know how to initialize environement variables inside my Qt application and then retrieve them to use in different classes.
    For example I would like to set a environment variable for an API URL (the world famous "http://localhost:8080/") to use it in different services.

    I've saw the documentation on the QProcessEnvironment class but I have to say that with my beginner level it is a bit confusing.

    Also I've saw on many formum posts, environment variable initialized like this:

        QProcess process;
        QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
        env.insert("AKEY", "avalue");
        env.insert("BKEY", "bvalue");
        process.setProcessEnvironment(env);
    

    But some where posted many years ago. So is it still as good way initialize environment variables ? Can it be done in other class than the main ? And finally how to retrieve the variable ?

    Thank you for reading.


  • Lifetime Qt Champion

    @Aymeric_Qt said in How to set environment variables properly:

    (create a new one which will contains the required variables) ?

    Yes :)
    instead using global variables, we put the needed data in a class

    struct Data { // give better name :)
    QString BaseURL{"http://localhost:8080/"};
    int TimeOut=1800;
    ...
    }

    and then for the classes that need this, we change its constructor so it can accept
    an extra parameter of type "Data" or Data & or Data *
    Just give them´copy if all just read it. if they also have to alter the data, then & or *

    Like
    Data MyData; // make SURE the actual data lives until end of app.

    MyHttp *http = new  MyHttp (this, &Mydata);
    

    the class will then store it in a member variable for later use in other
    functions than ctor.


  • Lifetime Qt Champion

    The way is correct according the docs.


  • Lifetime Qt Champion

    Hi,

    Your last question is a bit surprising, why do you want to retrieve the environment variable you use for a QProcess ?



  • @Aymeric_Qt
    What is your actual question?

    The example you show sets environment variables to be passed to a sub-process, only. It has nothing to do with your calling program's environment. It may not be what you should be doing, difficult to know.



  • As others have noted, changes you make to the Qt program environment will be available only to child processes of your Qt App: ie QProcess spawned programs. Your comment about making the vars available to other classes is poor design methodology, if in fact that is your reason for stuffing the environment.

    Making data available among classes is done thru a variety of internal mechanisms, such as signal/slots, or a global data store object accessible to the classes of your program.



  • Hi,
    Thank you all for your replies.

    Given your replies it seems that I've made a mistake about what QProcess and QProcessEnvironement are made for.
    So my question would be:
    How to set variables which could be use in mutiple class inside the application ?

    Those kind of variables that would be put in an application.properties file in a Java/Spring Boot app (like API URL, database connexion info etc...).


  • Lifetime Qt Champion

    @Aymeric_Qt said in How to set environment variables properly:

    How to set variables which could be use in mutiple class inside the application ?

    There is no need for environment variables for that.
    You can easily exchange information between classes. There are many ways to do so:

    • Pass parameters to class constructor
    • Global variables (try to avoid as much as possible!)
    • Put such variables in a header as "extern" and include the header where needed
    • ...

    Maybe you can explain your use case to get best answer?



  • @jsulm Hi,

    To explain quickly, my Qt application is a desktop client which consumes a very basic REST API to do CRUD operation.

    To communicate with my API I've created an http service class to handle all the http request/response logic. And as the API gets more complex (with more entities for example) I might would like to have mutiple http services to avoid to have one giant unmaintainable class.
    But for all those service the base of the API url will remain the same (http://localhost:8080/).
    So I woul like to be able to declare once and use it in different classes/services.

    Moreover in a production application this kind of variable is expected to change depending on the different environment where the application is use and/or with which api etc...

    So what would be the best way to achieve this?


  • Lifetime Qt Champion

    @Aymeric_Qt said in How to set environment variables properly:

    So what would be the best way to achieve this?

    Create this class and pass a pointer to this instance to all other classes who need to access it.
    In Qt a better way would be to use signals/slots (depends on exact use case).



  • @jsulm

    @jsulm said in How to set environment variables properly:

    Create this class and pass a pointer to this instance to all other classes who need to access it.

    Sorry I don't get which class you are talking about, the http service class or an another class (create a new one which will contains the required variables) ?


  • Lifetime Qt Champion

    @Aymeric_Qt said in How to set environment variables properly:

    (create a new one which will contains the required variables) ?

    Yes :)
    instead using global variables, we put the needed data in a class

    struct Data { // give better name :)
    QString BaseURL{"http://localhost:8080/"};
    int TimeOut=1800;
    ...
    }

    and then for the classes that need this, we change its constructor so it can accept
    an extra parameter of type "Data" or Data & or Data *
    Just give them´copy if all just read it. if they also have to alter the data, then & or *

    Like
    Data MyData; // make SURE the actual data lives until end of app.

    MyHttp *http = new  MyHttp (this, &Mydata);
    

    the class will then store it in a member variable for later use in other
    functions than ctor.



  • @mrjj Hello,

    Thanks for your reply!
    Meanwhile I've made something maybe a little bit strange.

    I've created a configuration class which is retrieving the request data in a Json file (might not be the best data format to store a configuration variables) and store it into a member variable.
    Then I've get this value in the class that need it inside the constructor.
    Those code samples will be moremeaningful:

    configuration.h:

    public:
        explicit configuration(QObject *parent = nullptr);
    
        QString getApiUrl();
    
    private:
    
        QString m_apiUrl;
    
        void init();
    

    configuration.cpp:

    configuration::configuration(QObject *parent) : QObject(parent)
    {
        init();
    }
    
    QString configuration::getApiUrl()
    {
        return m_apiUrl;
    }
    
    void configuration::init()
    {
        QString config;
        QString configFile = QDir::currentPath() + QDir::separator() + "configuration.txt";
        QFile file(configFile);
    
        if(!file.open(QIODevice::ReadOnly))
        {
            qDebug() << file.errorString();
        }
        config = file.readAll();
        file.close();
    
        QJsonDocument configJson = QJsonDocument::fromJson(config.toUtf8());
        QJsonObject configObject = configJson.object();
    
        m_apiUrl = configObject["apiUrl"].toString();
    }
    

    http_service.h:

    private:
        configuration *config = new configuration(this);
        QNetworkAccessManager nam;
        QString m_apiUrl;
    

    http_service.cpp:

    httpService::httpService(QObject *parent) : QObject(parent)
    {
        m_apiUrl = config->getApiUrl();
    }
    

    But I think I'll do has you say, it will be much cleaner.

    Once again thank you all for your comments and replies.


Log in to reply