Home > Software engineering >  Accessing Function from a Nested Include in C
Accessing Function from a Nested Include in C

Time:08-22

Trying to understand more complex project structure in C . This is for an nrf52840 (embedded 2.4Ghz radio device). But the question is about C but using it for an example.

Say I have 5 files I created:

1) main.cpp
2) mouse.cpp
3) mouse.h
4) radio_controls.cpp
5) radio_controls.h

There is also a .h I included:

1) esb.h

In esb.h there is a function called esb_set_rf_channel(int) which is used to set a frequency on the radio device to receive and transmit on. I included it in radio_controls.h since I use functions defined in esb.h in the radio_controls.h and radio_controls.cpp.

I included radio_controls.h in mouse.cpp since I need to control the radio device for the mouse to mostly transmit move commands.

Is this even proper? What is the recommended standard? I now can call esb_set_channel(int) directly in mouse.cpp but the intent was to have all the radio stuff in radio_controls and maybe have a helper member function call it for me from radio_controls. I also want to avoid including header files too many times where you might start to run into issues since esb.h is not my file as a project gets larger I could see this as an issue.

Edit: Code for more clarity. Main problem is I need a structure from esb.h in radio_controls.h. Maybe I could have a struct of my own for the settings I want to change and have the implantation file create the esb.h struct on the stack? This seems terrible too.

radio_controls.h

#ifndef RADIO_CONTROLS_H
#define RADIO_CONTROLS_H

#include <esb.h>

class RadioControls {
private:
    esb_config config; // this structure is from esb.h (this is why I need the #include <esb.h> here

    // config changes from default that need to be added by mouse
    // and need to set RF 
    //config.retransmit_delay = 250; // lower retransmit delay from default of 600 
    //config.event_handler = event_handler; // add radio event handler

    int clocks_start(void); // start HF clock (needed for ESB to work)
    int esb_initialize(void); // initialize esb radio
    // want a structure for esb initialize values to be passed in

    // rx and tx payloads
    static struct esb_payload rx_payload;
    static struct esb_payload tx_payload;

public: 
    RadioControls(); // initialize radio on nrf device
    int esb_set_rf_channel(uint32_t channel); // set rf channel to first element in array of unifying
    // could be a helper function like set_rf(uint32 channel); and implementation file calls esb.h defined one

}; // namespace controls::radio

#endif // RADIO_CONTROLS_H



#ifndef MOUSE_H
#define MOUSE_H

/*
 * Initialize mouse.
 * 
 * And need to restore any settings from 
flash. 
 * 
 */
class mouse {
    private:
    // restore mouse settings from flash

public:
    Mouse(); // create unifying mouse
    // ~Mouse(); // reset to default and disable

    // int move_mouse(); // x, y mouse move command

    // initialize esb radio

    // set radio to default settings for mouse
    // this includes RF, address for pipes, etc. 
};

#endif // MOUSE_H

CodePudding user response:

There's a little rule that helps me make my code a little bit clear. The rule sounds like that:

Do not add include directives in header files

Sometimes it's impossible, and that's OK. In your solution, you can make your radio_controls.h as clear as possible. Something like that:

#pragma once

namespace controls::radio {

using result_t = unsigned char;

result_t initialize();

result_t set_channel(const unsigned char channel);

} // namespace controls::radio

And your cpp file could be like:

#include "radio_controls.h"
#include <esb.h>

namespace controls::radio {

result_t initialize() {
    return esb_init();
}

result_t set_channel(const unsigned char channel) {
    return etb_set_rf_channel(channel);
}

} // namespace controls::radio

I didn't use classes in my examples because, as I understand, you're an embedded developer, but I still highly recomend to use classes in a case like that. You could make a class named radio::Controls or etc. But, of course, if your compiler allows doing it. Anyway, I hope I answered to your question.

Assuming I can make another rule:

Include additional functionality only in those files, where you really need it. Avoid to add includes into header files

CodePudding user response:

@Steve4879, yes, There's a way to use structures from the esb.h. You can use forward declaration for it. Take a look:

#pragma once

#include <memory>

class ClassFromLibrary;
struct StructFromLibrary;

namespace controls::radio {

std::shared_ptr<ClassFromLibrary> makeClassFromLib(const StructFromLibrary &data);

// here will be error:
ClassFromLibrary makeClassFromLib(StructFromLibrary data);
// Because the forward declared classes can only be pointers or referencies

} // namespace controls::radio

  • Related