【问题标题】:How to create global object accessible to src/ code as well as lib/ libraries?如何创建可供 src/ 代码和 lib/ 库访问的全局对象?
【发布时间】:2019-01-12 17:22:07
【问题描述】:

我正在尝试开始使用 PlatformIO,但遇到了包含优先级和/或变量范围的问题。

我的代码由一个src/main.cpp 程序以及几个位于lib/<libname>/*.cpp/h 位置的私有库组成。

我想要一个外部类 (Syslog) 的全局对象,我的主程序和我添加的任何私有库都可以访问它。

我目前尝试了两种方法,都拒绝编译:


在main.cpp中使用extern关键字创建对象,在setup()中初始化对象如下:

src/main.cpp:

#include <Syslog.h>
#include <WiFiUdp.h>
WiFiUDP SyslogUDP;
extern Syslog syslog;
void setup()
{
   syslog = Syslog(SyslogUDP, "255.255.255.255", 514, "FlyballETS", "FlyballETSApp", LOG_INFO, SYSLOG_PROTO_BSD);
}

lib/GPSHandler/GPSHandler.cpp:

void GPSHandlerClass::init(HardwareSerial * SerialPort)
{
   syslog.logf_P("GPS Class initialized!");
}

这会导致编译器错误,例如:

lib\GPSHandler\GPSHandler.cpp:22:4: error: 'syslog' was not declared in this scope

我尝试的第二种方法(在 Arduino IDE 中有效)是创建一个小的 SyslogHelper.h 文件,该文件创建了 extern Syslog syslog; 对象,然后将此帮助文件包含在我所有的私有库中,如下所示:

src/main.cpp:

#include "SyslogHelper.h"
#include <WiFiUdp.h>
WiFiUDP SyslogUDP;

void setup()
{
   syslog = Syslog(SyslogUDP, "255.255.255.255", 514, "FlyballETS", "FlyballETSApp", LOG_INFO, SYSLOG_PROTO_BSD);
}

src/SyslogHelper.h:

#include <Syslog.h>
extern Syslog syslog;

lib/GPSHandler/GPSHandler.cpp:

#include "SyslogHelper.h"
void GPSHandlerClass::init(HardwareSerial * SerialPort)
{
   syslog.logf_P("GPS Class initialized!");
}

当我尝试在 PlatformIO 中编译它时,它失败了,因为在它尝试编译 SyslogHelper.h 时,它似乎不知道 &lt;Syslog.h&gt; 文件的位置:

In file included from lib\GPSHandler\GPSHandler.cpp:7:0:
src/SyslogHelper.h:4:20: fatal error: Syslog.h: No such file or directory

【问题讨论】:

    标签: c++ arduino platformio


    【解决方案1】:

    虽然我意识到您说您希望在库和私有库之间共享一个全局对象,但我要断言这不是最好的设计模式,因为它脆弱且容易出错(正如您所经历的那样)。更好的方法是将您在主代码中创建的SysLog 对象作为参数传递给任何需要它的方法。这样做更好的原因是因为您明确声明了哪些方法可以并且应该使用Syslog 对象。

    但是,如果您确实必须有一个全局变量,那么第二好的模式是使用如下所示的访问器类:

    SysLogHelper.h

    #ifndef __SysLogHelper_h__
    #define __SysLogHelper_h__
    
    #include <Syslog.h>
    
    class SysLogHelper {
    private:
        Syslog *_instance;
    
    public:
        static Syslog& instance( void );
    
        Syslog();
        virtual ~Syslog()
    }
    #endif // __SysLogHelper_h__
    

    SysLogHelper.cpp

    #include "SysLogHelper.h"
    
    SysLogHelper gSysLogHelper();
    
    Syslog& SysLogHelper::instance( void ) {
        return gSysLogHelper._instance;
    }
    
    SysLogHelper::SysLogHelper() {
        _instance = Syslog(SyslogUDP, "255.255.255.255", 514, "FlyballETS", "FlyballETSApp", LOG_INFO, SYSLOG_PROTO_BSD);
    }
    
    SysLogHelper::~SysLogHelper() {
        delete _instance;
    }
    

    然后在您想要使用SysLog 对象的代码中的任何位置,只需包含SysLogHelper.h 标头,并通过调用静态方法来使用您的SysLog 实例,如下所示:

    #include "SyslogHelper.h"
    void GPSHandlerClass::init(HardwareSerial * SerialPort)
    {
       SyslogHelper::instance().logf_P("GPS Class initialized!");
    }
    

    您可以根据自己的喜好随意重命名。此外,通过一些创意,您可以在此访问器类中拥有多个 SysLog 对象,每个对象的配置都不同。

    【讨论】:

      猜你喜欢
      • 2013-05-30
      • 1970-01-01
      • 2015-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-09
      • 2015-03-22
      • 2011-08-25
      相关资源
      最近更新 更多