本文最后更新于:2021年11月30日 晚上
前情提要
众所周知,在Windows
中访问底层网络需要用到WinPcap
这个工具
比如,Wireshark
(网络封包分析软件)就用到了WinPcap
那么,如何在Qt
平台中使用WinPcap
呢?
安装 WinPcap for Qt
众所周知,C++
想要使用库,就必须提供.h .lib .dll
等文件,那么只要下载对应文件即可
WinPcap官网
1.首先下载安装winpcap.exe
目的是安装相关驱动和dll,安装完成之后基于winpcap的应用程序才能够正常运行
2.下载winpcap的开发包,头问文件和库文件
解压即可得到 Include & Lib 文件夹
From windows下安装配置winpcap - sunnycs - 博客园
接下来,我们需要在Qt
中引用这些文件(假设解压目录:E:\WpdPack
)
在.pro
文件中添加:
1 2 3
| INCLUDEPATH += E:/WpdPack/Include LIBS += E:/WpdPack/Lib/x64/wpcap.lib \ E:/WpdPack/Lib/x64/Packet.lib
|
用以引入头文件和库文件路径
然后在mainwindow.h
文件中引入头文件"pcap.h"
以测试是否成功安装
正文:Error
果不其然,琳琅满目的30个报错:
1 2 3 4
| E:\Qt5.14.2\Tools\mingw730_64\x86_64-w64-mingw32\include\stdio.h:735: error: conflicting declaration of 'int _snprintf(char*, size_t, const char*, ...)' with 'C' linkage _CRTIMP int __cdecl _snprintf(char * __restrict__ _Dest,size_t _Count,const char * __restrict__ _Format,...) __MINGW_ATTRIB_DEPRECATED_SEC_WARN; ^~~~~~~~~
|
不过仔细观察
错误多为:conflicting declaration (定义冲突)& has not been declared (未声明)
且翻来覆去就那几个函数:_snprintf() _vsnprintf()
而且而且,貌似都跟 stdio.h 有关
列文虎克
等一下,我们引入的是 pcap.h
头文件,为什么会引发标准库错误
まさか、真実はいつも一つ
让我们进入 pcap.h
の pcap/pcap.h
の pcap-stdinc.h
发现了令人震惊的一幕:
1 2 3 4 5
| #if _MSC_VER < 1500 #define snprintf _snprintf #define vsnprintf _vsnprintf #define strdup _strdup #endif
|
这个头文件 居然对 snprintf
& vsnprintf
函数进行了#define
替换
众所周知,#define
的作用域是该语句到文件尾
好巧不巧,该语句后正好有 #include<stdio.h>
而 stdio.h
中又同时定义了 snprintf
_snprintf
& vsnprintf
_vsnprintf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| int vsnprintf (char * __restrict__ __stream, size_t __n, const char * __restrict__ __format, va_list __local_argv) { return __ms_vsnprintf (__stream, __n, __format, __local_argv); }
int snprintf (char * __restrict__ __stream, size_t __n, const char * __restrict__ __format, ...) { register int __retval; __builtin_va_list __local_argv; __builtin_va_start( __local_argv, __format ); __retval = __ms_vsnprintf (__stream, __n, __format, __local_argv); __builtin_va_end( __local_argv ); return __retval; }
__attribute__((__format__ (ms_printf, 3, 4))) __MINGW_ATTRIB_NONNULL(3) _CRTIMP int __cdecl _snprintf(char * __restrict__ _Dest,size_t _Count,const char * __restrict__ _Format,...) __MINGW_ATTRIB_DEPRECATED_SEC_WARN; __attribute__((__format__ (ms_printf, 3, 0))) __MINGW_ATTRIB_NONNULL(3) _CRTIMP int __cdecl _vsnprintf(char * __restrict__ _Dest,size_t _Count,const char * __restrict__ _Format,va_list _Args) __MINGW_ATTRIB_DEPRECATED_SEC_WARN;
|
导致 snprintf
vsnprintf
被替换为 _ 下划线版本 导致重定义
同时导致<QMainWindow
>中引用了 stdio.h
的标准库文件 都出现了snprintf
vsnprintf
未定义问题
对策
既然 #define
的作用域是垂直向下的,那么只要把 stdio.h
从其下方排除即可
为了最大限度避免修改头文件
我们需要用到另一个性质:
头文件一半为了防止重复包含,一般会写上:
1 2 3 4
| #ifndef STH_H #define STH_H ... #endif
|
所以头文件不会二次引用
也就是说,只要在 那个罪恶的 #define
之前 写下 #include<stdio.h>
:
1 2
| #include <stdio.h> #include "pcap.h"
|
这样 pcap.h
中的 #include <stdio.h>
就不会生效 也不会产生替换了
而其他位置的snprintf
vsnprintf
替换并无大碍(我猜的),因为都有定义
或者
1 2
| #include <QMainWindow> #include "pcap.h"
|
peace
Reference
使用Winpcap示例程序的时候,会出现很多错误(转)_天道酬勤-CSDN博客