(二)wireguard-tools源码解读之main


源码解读

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
 */

#include <stddef.h>
#include <stdio.h>
#include <string.h>

#include "subcommands.h"
#include "version.h"

const char *PROG_NAME;
/*
这个静态数组,是wg的子命令列表,
char *subcommand,是子命令名称,也就是在wg后面跟着的第一个参数;
int (*function),函数指针,就是函数进入到内存后的地址信息,通过这个地址信息直接调用函数,因为是数组方式,所以每一项内容占用的内存大小一样。后面专门解释一下。
char *,对于该子命令的描述。
*/
static const struct {
	const char *subcommand;
	int (*function)(int, const char**);
	const char *description;
} subcommands[] = {
	{ "show", show_main, "Shows the current configuration and device information" },
	{ "showconf", showconf_main, "Shows the current configuration of a given WireGuard interface, for use with `setconf'" },
	{ "set", set_main, "Change the current configuration, add peers, remove peers, or change peers" },
	{ "setconf", setconf_main, "Applies a configuration file to a WireGuard interface" },
	{ "addconf", setconf_main, "Appends a configuration file to a WireGuard interface" },
	{ "syncconf", setconf_main, "Synchronizes a configuration file to a WireGuard interface" },
	{ "genkey", genkey_main, "Generates a new private key and writes it to stdout" },
	{ "genpsk", genkey_main, "Generates a new preshared key and writes it to stdout" },
	{ "pubkey", pubkey_main, "Reads a private key from stdin and writes a public key to stdout" }
};

static void show_usage(FILE *file)
{
	fprintf(file, "Usage: %s <cmd> [<args>]\n\n", PROG_NAME);
	fprintf(file, "Available subcommands:\n");
	for (size_t i = 0; i < sizeof(subcommands) / sizeof(subcommands[0]); ++i)
		fprintf(file, "  %s: %s\n", subcommands[i].subcommand, subcommands[i].description);
	fprintf(file, "You may pass `--help' to any of these subcommands to view usage.\n");
}

int main(int argc, const char *argv[])
{
	/*
	把输入的程序名称wg,先保留起来,主要用于后面输出提示信息用。
	*/
	PROG_NAME = argv[0];
    /*
	wg命令,如果只输入一个参数,并且这个参数是-v或--version或versiond,直接打印版本信息,return 0。
		   如果只输入一个参数,并且这个参数是-h或--help或help,展示语法信息,return 0。

		   如果不输入任何参数,则调用show_main()

		   如果输入多个参数,则需要对第一个参数进行检索,检索成功后,调用相应的函数指针,这个函数指针,并且把在命令行输入的参数进行剪裁后传给这个函数。
		                  argc-1 就是传入的参数数量;argv+1,就是把原来命令行参数的指针往下走一个,这就是把输入的"wg"去掉后,重新传给了函数指针。
	       如果输入了多个参数,并且没有检索成功,则输出错误命令提示,return1。
	*/
	if (argc == 2 && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version") || !strcmp(argv[1], "version"))) {
		printf("wireguard-tools v%s - https://git.zx2c4.com/wireguard-tools/\n", WIREGUARD_TOOLS_VERSION);
		return 0;
	}
	if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "help"))) {
		show_usage(stdout);
		return 0;
	}

	if (argc == 1) {
		static const char *new_argv[] = { "show", NULL };
		return show_main(1, new_argv);
	}

	for (size_t i = 0; i < sizeof(subcommands) / sizeof(subcommands[0]); ++i) {
		if (!strcmp(argv[1], subcommands[i].subcommand))
			return subcommands[i].function(argc - 1, argv + 1);
	}

	fprintf(stderr, "Invalid subcommand: `%s'\n", argv[1]);
	show_usage(stderr);
	return 1;
}

备注:函数指针

关于函数指针的用法,本人认为是C语言的经典精华部分,在各大高性能软件中,都会看到类似的用法,尤其是在Nginx的源码中,更是用到极处。
比如在nginx源码中:typedef size_t (*ngx_log_handler_pt) (void *ctx, char *buf, size_t len);
举个最直接简单的例子吧,

#include <iostream>
using namespace std;
typedef int (*Pointer) (char, char);
 
int ss(char a, char b)
{
    cout<<"in func ss()"<<endl;
    cout<<a<<endl;
    cout<<b<<endl;
 
    return 0;
}
 
int bb(char a, char b)
{
    cout<<"in func bb()"<<endl;
    cout<<b<<endl;
    cout<<a<<endl;
 
    return 0;
}
 
int main()
{
    Pointer p;
    p = ss;
    p('a','b');
    p = bb;
    p('a', 'b');
    return 0;
}

通过p来调用两个函数。
运行结果:

in func ss()
a
b
in func bb()
b
a

当然了,这种函数指针,跟静态数组以及偏移量结合起来使用,不但能简洁源代码,并且能大大提升程序的运行效率。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
labelimg-master是一个用于标注图像的开源工具,它是基于Python和Qt开发的。这个工具可以让用户在图像上画框并添加标签,以标注出感兴趣的目标物体,从而用于训练计算机视觉模型。下面我将对其源码进行简要解读。 首先,整个源码结构清晰,主要包括四个文件夹:libs、libs/qt_py、libs/pyqt5_tools、libs/resources,以及一个主文件labelImg.py。libs文件夹包含了一些辅助功能模块,如将XML文件转换为CSV文件、生成TFRecord文件等。libs/qt_py包含了一些用于兼容不同Python版本的代码。libs/pyqt5_tools包含了一些自定义的PyQt5小工具,用于增强用户体验。libs/resources包含了一些图标和界面样式文件。 主文件labelImg.py则负责整个应用的逻辑处理和界面显示。在这个文件中,首先通过一系列的导入语句引入了所需的库和模块。然后定义了一些全局变量,如默认的标注类别、保存文件的格式等。接下来是一些辅助函数的定义,用于处理图像的加载、保存、显示等操作。 整个应用的主要逻辑是基于PyQt5框架实现的。通过定义了一个名为App的类,实现了应用的主窗口、工具栏、菜单栏等界面组件的创建和显示。这个类还包括了一些事件处理函数,如鼠标点击、键盘按下等事件的响应函数。 当用户通过界面选取了待标注的图像后,系统会调用相关函数将图像加载并显示在界面上。用户可以使用鼠标在图像上划定目标物体的边界框,并选择合适的标签。在保存标注结果时,系统会将标签和边界框的信息保存为XML文件或CSV文件,以供后续使用。 总的来说,labelimg-master是一个功能简单、易用的图像标注工具,使用Python和Qt开发。它提供了方便的界面操作和灵活的标注方式,可以满足大多数标注需求。通过深入阅读源码,我们可以了解它的实现原理,进一步定制和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值