记录自己目前开发arduino单片机程序过程中将项目拆分到多个.C和.H文件

 

单文件项目弊病

 

项目代码比较大,改点东西来回找,鼠标够你滚了...

 

 

拆分项目

将项目拆分到多个.H/.C文件,好处就是一个文件处理一部分内容,web相关的放一个文件,如果有问题只需要定位这个文件然后修改.

 

加防重复引入标记.

方式1,

H文件用预处理指令判断一个特定宏是否存在,如果不存在就定义一次.

这样就相当于第一次被引用的时候,会定义,之后全部过跳过.

 

 

#ifndef WEB_FUN_H
#define WEB_FUN_H


//代码


#endif

 

方式2

一次性引入标记

#pragma once

 

两个效果差不多.没做细细了解,我喜欢方式1.

 

 

 

extern 关键字

 

引用的过程中,难免调用其他H或者C中的函数,

如果编译器抛出错误.变量,或者函数未定义.

那么就考虑用这个关键词.

 

作用是:

告诉编译器,extern 后面跟着的函数/变量在其他地方已经定义了.

 

//引用其他文件的函数,和定义函数原型一样.
extern void test(void);

//引用其他文件的变量
extern int abc;

 

项目构建

 

我在拆分过程碰到各种问题.

下面是我简单的综合的解决方案.

方法有点怪癖,非常规方案.

 

1,仅一个入口的C文件.

也就是,main.c是c文件,

其他的全是H文件.其他的H文件当C文件用.

 

这里main.c不引用任何外部库/头文件.(也就是带尖括号引用的H文件都不在这里引用)

这里引用的全是自己的H文件

第一个引用common.h

 

#include "common.h"

#include "fs_fun.h"
#include "ap_fun.h"


///..........

2,定义一个common.h 文件

 

首这个文件,负责引用全部的外部库文件.

#include <FS.h>
#include <DNSServer.h>

#include <EEPROM.h>

#include <Esp.h>

#include <ArduinoJson.h>
#include <time.h>



//引用自己的变量定义的h文件
#include "config.h"

//.............

 

引入了外部库在先, 自定义变量文件H在后,

这样在config.h 可以直接定义这些外部库中的特定类型. 

不需在config.h引用对应的外部库

 

 

3,定义一个config.h存放全局变量

 

common.h 先引用了

然后再引用了 "config.h"

 

那么再config.h中,无需再引用

即可调用这个库内的类型.

 

EspClass espclass;

 

 

 

4, common.h 文件放全部的函数原型.

还是common.h这个文件.

 

 

因为我的方法有点另类.我将所有的H文件当C文件使用

也就是H文件直接写函数本体,而不写函数原型.

 

但是C系的程序永远是先定义后使用.

 

所以还是需要先定义.

 

避免各种互相调用的问题.我将全部的函数原型集中放在common.h中

 

(当然,可以在common.h再引用一个h文件,专门存放函数原型.可以将其放common.h内容最后.这里不验证,理论上是可以的)

 

我放在common.h中函数原型大致如下.

 

定义非常简单,只需要在原型前面加上关键字 extern 就可以为所欲为了.

//---------------mqtt_fun::start-------------------------
extern void mqtt_reconnect();
//---------------mqtt_fun::end-------------------------

//---------------ap_fun::start-------------------------
extern String makePage(String title, String contents);
extern void WIFIlistJs();
extern void Restart_b();

//---------------ap_fun::end-------------------------

//---------------fs_fun::start-------------------------
extern String formatBytes(size_t bytes);
extern String getContentType(String filename);
extern bool handleFileRead(String path);
extern bool saveConfig(String jsonConfig);
extern bool readConfig();
#if defined(IS_DEBUG)
extern void handleFileList();
#endif

//---------------fs_fun::end-------------------------

 

这样不同H文件调用其他H内的函数,直接用,无需作任何引用头