Modbus软件开发实战指南 之 开发自己的Modbus Poll工具 - 2

接上一篇文章的内容。

看了前面需求提到的复杂的命令行解析功能,很多人立马开始发怵,其实大可不必。

我们都知道,Linux下的程序往往都提供了复杂的命令行参数处理机制,因为这是与

其他程序或用户进行交互的主要手段,在这样的情况下难能可贵的是,为了减轻开发

人员对命令行处理的负担,Linux提供了系统函数getopt()或getopt_long()专门解析命令行参数。

在Linux系统中,函数getopt()/getopt_long()位于 unistd.h 系统头文件中,其原型分别为:

int getopt(int argc,char * const argv[],const char * optstring);

int getopt_long(int argc, char * const argv[],const char *optstring,

const struct option *longopts, int *longindex);

其中,参数argc和argv是由主函数main()传递的参数个数和内容。

参数optstring 则代表欲处理的选项字符串。此函数会返回在argv 中下一个的选项字母,

此字母会对应参数optstring 中的字母。如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,

全域变量optarg 即会指向此额外参数。如果getopt()找不到符合的参数则会打印出错信息,并将全域

变量optopt设为“?”字符,如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。

参数可简单划分为短参数和长参数两种类型,getopt()使用optstring所指的字串作为短参数列表,

象“1ac:d::”就是一个短参数列表。短参数的定义是一个‘-‘后面跟一个字母或数字,象-a, -b就是一个

短参数,每个数字或字母定义一个参数。

而长参数则形如“--debug”,前面有2个‘-‘符号,后面可添加多个字母或数字。

getopt_long()函数包含了getopt()函数的功能,并且还可以指定“长参数”(或者说长选项),

与getopt()函数对比,getopt_long()比getopt()多了两个参数。

此函数的基本用法如下(Linux下):


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25


#include <stdio.h>
#include <unistd.h>

int main(int argc, int *argv[])
{
    int ch;
    opterr = 0;

// getopt()可由getopt_long()替换
    while ((ch = getopt(argc, argv, "a:bcde")) != -1)
    {
        switch(ch)
        {
        case ‘a‘:
            printf("option a:‘%s‘\n", optarg);
            break;
        case ‘b‘:
            printf("option b :b\n");
            break;
        default:
            printf("other option :%c\n", ch);
        }
    }
    printf("optopt +%c\n", optopt);
}

以上作为参照,可见调用函数getopt()或getopt_long()可以非常方便地解析命令行。

但是,有一点遗憾的是,如此方便的函数在Windows下却没有提供,怎么办呢?当然有办法了,

既然函数getopt()/getopt_long()是GNU C中的函数,那么源码可见就可以根据情况直接移植到Windows下。

说干就干,接下来简要介绍一下移植方法,掌握一点新技能,如果对这部分没有兴趣,可以跳过,看后面的内容。

首先,访问GNU C Library (glibc)的主页http://www.gnu.org/software/libc/,并下载最新的glibc库,

当前最新版是glibc-2.24.tar.gz,下载完毕并解压。

提取加压后的目录\glibc-2.24\posix\下的4个源文件getopt.h/getopt.c/getopt_int.h/

getopt_init.c,如图所示。

图 提取getopt()相关文件

启动Visual Studio 2015,选择菜单【File】->【New】->【Project...】,

准备创建一个新的默认工程项目,项目类型为【Visual C++】→【Win32
Console Application】。

创建新的默认工程项目完毕之后,切换到资源管理器画面,将以上4个文件复制到新项目所在目录,并添加到工程项目中,如图所示。

图 添加getopt()源文件

文件添加完毕之后,我们试着编译一下看看,果不其然,文件getopt.c出现了编译错误:

getopt.c(71): fatal error
C1083: Cannot open include file: ‘gettext.h‘:
No such file or directory

首先需要修改的是没有“gettext.h”这个头文件的问题。修改方法为直接将其注释掉或删除,然后修改后面的宏定义。

将下面的原始代码(大概在70行):


1
2
3
4
5
6


#ifdef _LIBC
# include <libintl.h>
#else
# include "gettext.h"
# define _(msgid) gettext (msgid)
#endif

修改为:


1
2
3
4
5


#ifdef _LIBC
# include <libintl.h>
#else
# define _(msgid)  (msgid)
#endif

修改完毕,继续编译一下看看,出现如下编译错误,如图所示。

                    

图 编译错误alloca无法识别

错误的文字描述为:

getopt.c(568): warning
C4013: ‘alloca‘ undefined; assuming
extern returning int

error LNK2019: unresolved external symbol _alloca
referenced in function __getopt_internal_r

可以发现,这里出错的原因是alloca这个函数没有定义,那么alloca函数是什么意思呢?

原来alloca是一个内存分配函数,与malloc、calloc、realloc类似,但是注意一个重要的区别,

alloca函数是在栈(stack)上申请空间,用完马上就释放。

一般情况下,函数alloca包含在头文件malloc.h中,在某些系统中被定义为内部函数_alloca的宏定义。

既然已经知道原型了,那么修改alloca为_alloca即可解决问题,如图所示。

图 修改为_alloca解决编译错误

继续添加getopt_long()/getopt_long_only()的定义,这两个函数在getopt.h文件中声明了,

但是其定义在getopt1.c中,可以直接将getopt1.c文件也拿过来用,但是因为这个文件中的内容不多,

为了减少文件的数量,直接将其中有用的部分拷贝到getopt.c文件中是个不错的主意。

文件getopt1.c中要拷贝的内容如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36


int
getopt_long (int argc, char *const *argv, const char *options,
             const struct option *long_options, int *opt_index)
{
    return _getopt_internal (argc,argv,options,long_options,opt_index,0,0);
}

int
_getopt_long_r (int argc, char *const *argv, const char *options,
                const struct option *long_options, int *opt_index,
                struct _getopt_data *d)
{
    return _getopt_internal_r(argc,argv,options,long_options,opt_index,
                               0, d, 0);
}

/* Like getopt_long, but ‘-‘ as well as ‘--‘ can indicate a long option.
   If an option that starts with ‘-‘ (not ‘--‘) doesn‘t match a long option,
   but does match a short option, it is parsed as a short option
   instead.  */

int
getopt_long_only (int argc, char *const *argv, const char *options,
                  const struct option *long_options, int *opt_index)
{
    return _getopt_internal(argc,argv,options,long_options,opt_index,1,0);
}

int
_getopt_long_only_r (int argc, char *const *argv, const char *options,
                     const struct option *long_options, int *opt_index,
                     struct _getopt_data *d)
{
    return _getopt_internal_r(argc,argv,options,long_options,opt_index,
                               1, d, 0);
}

将以上代码拷贝到文件getopt.c中函数getopt()定义之后即可,修改完毕编译,一切OK!

至此函数getopt()移植结束。经过上面的修改,可以进行一些简单的测试进行验证,

测试用例不用自己写了,在文件getopt.c和getopt1.c文件中都有,直接拿过来用就可以。

至此,重新生成的4个文件:getopt.h/getopt.c/getopt_int.h/getopt_init.c就是需要的命令行解析源代码文件,可以用在Windows系统下。

至此,针对自己开发modbus poll工具的命令行解析功能基本实现了。

接下来,将进行功能部分的代码分析和调试。

时间: 2024-10-20 20:01:21

Modbus软件开发实战指南 之 开发自己的Modbus Poll工具 - 2的相关文章

Hadoop应用开发实战(flume应用开发、搜索引擎算法、Pipes、集群、PageRank算法)

Hadoop是2013年最热门的技术之一,通过北风网robby老师<深入浅出Hadoop实战开发>.<Hadoop应用开发实战>两套课程的学习,普通Java开发人员可以在最快的时间内提升工资超过15000.成为一位完全精通Hadoop应用开发的高端人才. Hadoop是什么,为什么要学习Hadoop? Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式

《Python高效开发实战》实战演练——开发Django站点1

6.2 实战演练:开发Django站点 用Django开发网站需要遵循Django的一套开发流程.本节通过建立一个消息录入页面演示Django的开发流程及相关技术. 6.12.1  建立项目 在进行Django开发之前需要先用django-admin建立Django项目,语法如下: #django-adminstartproject 站点名称 其中django-admin是安装好Django组件后在Python目录中生成的django项目管理工具.比如,建立一个叫djangosite的开发项目:

&lt;java开发实战经典&gt;

<JAVA开发实战经典>&&<JAVA WEB开发实战经典> JAVA开发实战经典总结: 第一章:介绍 第二章:基本语法(数据类型.常量.变量.数据类型的强制转换)

Django企业开发实战 高效Python Web框架指南

高清PDF,带书签 Django企业开发实战 高效Python Web框架指南Django企业开发实战 高效Python Web框架指南Django企业开发实战 高效Python Web框架指南gACkM793118 粘贴链接到地址栏访问: https://fgk.pw/i/gACkM793118 原文地址:https://www.cnblogs.com/ziqang/p/11051134.html

面向Web Cloud的HTML5 App开发实战:Browser&amp;HTML5&amp;CSS3&amp;PhoneGap&amp;jQuery Mobile&amp; WebSocket&amp;Node.js(2天)

如何理解Android架构设计的初心并开发出搭载Android系统并且具备深度定制和软硬整合能力特色产品,是本课程解决的问题. 课程以Android的五大核心:HAL.Binder.Native Service.Android Service(并以AMS和WMS为例).View System为主轴,一次性彻底掌握Android的精髓. 之所以是开发Android产品的必修课,缘起于: 1,     HAL是Android Framework&Application与底层硬件整合的关键技术和必修技

Cocos2d-x+3.x游戏开发实战pdf

下载地址:网盘下载 内容简介  · · · · · · <Cocos2d-x 3.x游戏开发实战>是一本介绍Cocos2d-x游戏引擎的实用图书,全面介绍了最新的Cocos2d-x 3.2游戏引擎各方面的知识. <Cocos2d-x 3.x游戏开发实战>从内容层次上可分为四个部分.第一部分介绍了游戏开发的基础知识.游戏引擎概念.Cocos2d-x的下载与安装,以及跨平台开发环境的搭建.第二部分介绍了Cocos2d-x中的核心类.动作.动画.3D特效.文字.字体.菜单.事件处理.UI

企业级业务系统开发实战

通过一个系列讲述一个真实企业的ERP系统开发全过程.其中包括需求分析.设计建模.开发.测试全生命周期过程,其中会详细讲方法论与技术实践.涉及到的方法包括敏捷软件开发.四色原型.领域驱动设计.业务架构.技术架构与具体的EF.WF.EasyUI等技术在项目中的使用. 领域驱动设计案例之领域层框架搭建 摘要: 根据前面对领域驱动设计概念以及一些最佳实践的理解,领域模型是系统最核心的部分,我们还是采用前面销售订单的例子,这个案例系统的核心构建就从领域层开始.领域层框架搭建主要完成两个任务:1.领域模型的

《Android Studio开发实战 从零基础到App上线》资源下载和内容勘误

http://blog.csdn.net/aqi00/article/details/72907534 http://blog.csdn.net/aqi00/article/details/73065392 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 资源下载 下面是<Android Studio开发实战 从零基础到App上线>一书用到的工具和代码资源:1.本书使用的Android Studio版本为2.2.3,因为Android官网现在不提供该版本的下载,所以博主

【Mongodb教程 第十六课 】 分享NO-SQL开发实战

最近研究了一下NOSQL,现整理目录如下: 一.关系数据库的瓶颈: 二.NOSQL概述: 三.NOSQL中的热门数据库MongoDB介绍及安装配置: 四.MongoDB开发模式及实战: 一.关系数据库的瓶颈 从90年代到至今,关系数据库扮演了最重要的角色,它的性能,可扩展性.稳定性.数据的备份和恢复机制等都非常好,关系数据库发展到现在已经非常成熟,它提供给使用者的是一整套体系,包括数据存储.数据备份恢复.数据加解密.应用开发驱动.图形化配置维护工具.安全策略等等.图1中展示了世界上各种数据库的使