定义可变参数的函数的宏

需求 在 Linux 平台下运行程序时,需要通过 syslog 打印日志,syslog 本身是可变参数的函数,所以需要一个可变参数的宏来定义在 linux 平台下的函数。 解决 在 C++ 中,可变参数宏的写法是: #define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__), 满足需求的代码如下: #ifdef Q_OS_LINUX #define LOG(priority, format, ...) syslog(priority, format, ## __VA_ARGS__) #else #define LOG(priority, format, ...) #endif 在 C 中,写法是: #define debug(format, ...) fprintf(stderr, fmt, __VA_ARGS__) 在 GCC 中,写法是: #define debug(format, args...) fprintf (stderr, format, args) 参考 不定参数的宏 函数 整理:C/C++可变参数,“## __VA_ARGS__”宏的介绍和使用 c/c++巧用宏计算不定参数个数【不定参数】【宏】【#define】

2023-02-15 · 1 min · 63 words · RamLife

QT 在 win 平台编辑,在 Linux 平台调试

需求 需要在 windows 平台使用 qtcreator 编辑,在 linux 平台下编译并调试,综合考虑还是 samba 最简单适合。 解决 linux 设备建立 qt 的工程. 复制工程目录下的 .pro.user, 并重命名在后面增加 .linux 的后缀。 linux 设备开启 samba. 并把工程文件夹共享出来。 windows 设备把 samba 目录映射为网络驱动器。 windows 上的 qtcreator 打开 samba 中的工程,会提示工程有些问题,并让你重新选择编译工具。 qtcreator 会自动重命名原来的 .pro.user, 在后面追加一串字符。 在 linux 设备,复制工程目录下的 .pro.user, 并重命名在后面增加 .win 的后缀。 建立两个脚本文件,一个用来复制 .linux 覆盖当前的 .pro.user, 另一个是用 .win 来覆盖。 使用时,在 win 可以正常的进行代码编辑,在 linux 调试前,执行脚本,替换为 linux 的 .pro.user, 当调试完成后,返回 win 进行编辑时,再替换成 win 的 .pro.user. 参考 ubuntu 20.04 安装配置Samba服务,Windows 和 linux协同工作

2023-02-15 · 1 min · 72 words · RamLife

Ubuntu 20.04 安装配置 samba

需求 需要在 win 平台编辑代码,在 linux 平台进行编译和调试。这种情况只能使用 samba 才比较方便,nfs 必须双方都是 linux。 解决 安装 samba sudo apt install samba samba-common 共享目录 对于需要共享的目录可能需要使用 chmod 修改权限 如果共享的目录归属用户和 samba 用户一致,那么只要保证目录是 0755 即可 如果共享的目录归属用户组和 samba 用户的用户组一致,那么只要保证目录是 0775 即可 如果共享的目录归属用户和用户组和 samba 用户和用户组都不一致,那么只有修改目录权限为 0777 才可以。 chmod -R 777 /home/username/director 添加 samba 用户 添加已有用户为 samba 用户 sudo smbpasswd -a username 配置 samba 备份 samba 配置文件: sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak 在配置文件最后增加: [workspace] #共享名,该共享标签,可随意取,该名字为在其他电脑上看到的共享名 comment = work directories #该共享描述 browseable = yes path = /home/username/work #共享路径 valid users = username writable = yes #writable用来指定该共享路径是否可写 guest ok = no #指定该共享是否允许guest账户访问 read only = no create mask = 0775 directory mask = 0775 重启 samba 服务 sudo /etc/init....

2023-02-14 · 1 min · 119 words · RamLife

QT C++ 识别当前操作系统平台,并编译相应代码

需求 需要在 Qt 中检测当前的操作系统平台具体是 win 还是 linux,然后根据不同的平台执行不同的代码。比如在 linux 平台可以使用 syslog 解决 #ifdef Q_OS_LINUX #include <syslog.h> #endif #ifdef Q_OS_WIN #endif #ifdef Q_OS_OSX #endif #ifdef Q_OS_LINUX openlog(NULL, LOG_CONS | LOG_NDELAY | LOG_NOWAIT | LOG_PID, LOG_LOCAL0); setlogmask(LOG_UPTO(LOG_MASK_BUILD)); #endif syslog(LOG_DEBUG, "%s: %d: %s --> class construct", __FILE__, __LINE__, __FUNCTION__); 参考 Qt判断当前系统 QT C++识别当前操作系统

2023-02-14 · 1 min · 49 words · RamLife

系统日志 syslog 相关函数使用

需求 需要让 linux 平台的软件能够输出日志,便于后期的调试和分析。 解决 linux 平台原生支持 syslog 类型的日志服务,不同的发行版可能不同,有可能是 syslog, syslog-ng, rsyslogd 等等。但是具体的程序中输出日志的函数其实是一样的,主要就是三个函数 openlog(), syslog(), closelog(). 调用 syslog 函数之前,首先需要包含相应的头文件 #include <syslog.h> openlog 函数原型为: void openlog(const char *ident, int option, int facility);, 作用是打开一个到系统日志记录程序的连接,实际使用时,这个函数可以省略,在调用 syslog() 时,如果没有打开,会自动打开一个。但是显式使用 openlog 可以进行更多的设定。 ident, 设置日志中的生成者的标识,正常使用 NULL 就可以了,会使用程序名进行标识。如果需要自定义一个标识,那么输入字符串即可。 option, 设置日志相关属性,简单的可以使用 openlog(NULL, LOG_CONS|LOG_PID, 0); 即可,复杂的使用 openlog(NULL, LOG_CONS | LOG_NDELAY | LOG_NOWAIT | LOG_PID, LOG_LOCAL0);, 具体的含义可以 man openlog 可选配置 描述 LOG_CONS 直接写入系统控制台,如果有一个错误,同时发送到系统日志记录。 LOG_NDELAY 立即打开连接(通常,打开连接时记录的第一条消息)。 LOG_NOWAIT 不要等待子进程,因为其有可能在记录消息的时候就被创建了(GNU C库不创建子进程,所以该选项在Linux上没有影响。) LOG_ODELAY 延迟连接的打开直到syslog函数调用。(这是默认情况下,需要没被指定的情况下。) LOG_PERROR (不在SUSv3情况下)同时输出到stderr(标准错误文件)。 LOG_PID 包括每个消息的PID。 facility, 正常为 0 即可。 设置 描述 LOG_AUTH 认证系统:login、su、getty等 LOG_AUTHPRIV 同LOG_AUTH,但只登录到所选择的单个用户可读的文件中 LOG_CRON cron守护进程 LOG_DAEMON 其他系统守护进程,如routed LOG_FTP 文件传输协议:ftpd、tftpd LOG_KERN 内核产生的消息 LOG_LPR 系统打印机缓冲池:lpr、lpd LOG_MAIL 电子邮件系统 LOG_NEWS 网络新闻系统 LOG_SYSLOG 由syslogd(8)产生的内部消息 LOG_USER 随机用户进程产生的消息 LOG_UUCP UUCP子系统 LOG_LOCAL0~LOG_LOCAL7 为本地使用保留 syslog 函数原型为 void syslog(int priority, char*format,……);, 有需要输出的日志信息,就调用这个函数进行输出。...

2023-02-14 · 1 min · 142 words · RamLife

C 语言中 typedef 用法

需求 学习了解 typedef 在 c 语言中的用法 解决 基本解释 typedef 为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型( int, char 等)和自定义的数据类型( struct 等)。 在编程中使用 typedef 目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。 至于 typedef 有什么微妙之处,请你接着看下面对几个问题的具体阐述。 <!–more–> typedef & 结构的问题 当用下面的代码定义一个结构时,编译器报了一个错误,为什么呢?莫非C语言不允许在结构中包含指向它自己的指针吗?请你先猜想一下,然后看下文说明: typedef struct tagNode { char *pItem; pNode pNext; } *pNode; 答案与分析 typedef的最简单使用 typedef long byte_4; 给已知数据类型long起个新名字,叫byte_4。 typedef与结构结合使用 typedef struct tagMyStruct { int iNum; long lLength; } MyStruct; 这语句实际上完成两个操作: 定义一个新的结构类型. 分析: tagMyStruct 称为“tag”,即“标签”,实际上是一个临时名字, struct 关键字和 tagMyStruct 一起,构成了这个结构类型,不论是否有 typedef ,这个结构都存在。 我们可以用 struct tagMyStruct varName 来定义变量,但要注意,使用 tagMyStruct varName 来定义变量是不对的,因为 struct 和 tagMyStruct 合在一起才能表示一个结构类型。 struct tagMyStruct { int iNum; long lLength; }; typedef 为这个新的结构起了一个名字,叫 MyStruct 。因此, MyStruct 实际上相当于 struct tagMyStruct ,我们可以使用 MyStruct varName 来定义变量。 typedef struct tagMyStruct MyStruct; 结构体指针 C语言当然允许在结构中包含指向它自己的指针,我们可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于 typedef 的应用。...

2010-12-01 · 2 min · 365 words · RamLife

C 语言结构体数组,函数指针实现简单的菜单选项功能

需求 需要通过 C 语言实现简单的数码管或者段码液晶屏的简单的菜单选项功能 解决 结构体申明和定义 在 .h 文件中申明: typedef struct value_channel { unsigned char dir; unsigned int ADCValue[128]; }v_c; extern v_c value[4]; 在 .c 文件中定义 v_c value[4]; 函数指针 定义一个函数指针 void ( * fp)(void); 函数功能和跳转 void fun_start_01(void); { ...... } void fun_start(void) { switch(cs) { case 01: fp=fun_start_01; break; } } 在菜单调用的地方使用 ( * fp)(); 即可调用相应的菜单项。 函数地址 函数地址也可以放在数组中来调用: typedef void( * dis_turn)(void); void dis_turn_1(void) void dis_turn_2(void) dis_turn dis[]={dis_turn_1,dis_turn_2}; main() { dis[0](); dis[1](); } 实现菜单 typedef void(*FUN_P)(void);//(int Data) typedef struct Message_Item { unsigned char cStatus; FUN_P fnProcess; }MSG_ITEM; MSG_ITEM MSGMap[]={{0x00,fun_start},{0x01,fun_normal},{0x02,fun_set0},{0x03,fun_gas},{0x04,fun_set}}; void SearchMSGMAP(void) //(unsigned char cStatus) { unsigned char n=0; for(n=0;n<UBOND(MSGMap);n++) { if(MSGMap[n]....

2010-12-01 · 1 min · 108 words · RamLife