如何创建可供src/code和lib/libraries访问的全局对象

How to create global object accessible to src/ code as well as lib/ libraries?

本文关键字:lib code libraries 访问 对象 全局 src 何创建 创建      更新时间:2023-10-16

我正试图开始使用PlatformIO,但在包含优先级和/或变量范围方面遇到了障碍。

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

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

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


使用extern关键字在main.cpp中创建对象,在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!");
}

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

libGPSHandlerGPSHandler.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时,它似乎不知道<Syslog.h>文件的位置:

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

虽然我意识到你说你想要在库和私人库之间共享一个全局对象,但我要断言这不是最好的设计模式,因为它很脆弱,很容易出错(正如你所经历的)。一个更好的方法是将您在主代码中创建的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对象,每个对象的配置都不同。