2023年1月

C 语言已不再仅仅是一种编程语言

有一篇论文说,《C 语言不是一种低级别的编程语言》。它不是说有其他编程语言比 C 语言更低级,C 语言经常被称赞为 “接近于裸金属”,是一种 “可移植的汇编语言”。它曾经是,但自 20 世纪 70 年代以来就不是了;现代计算机的底层计算模型与 C 所代表的模型完全不同,它是为 20 世纪 70 年代的 16 位微型计算机设计的。任何语言开发的程序都必须与操作系统对接,而操作系统几乎都是用 C 语言开发的。换句话说,即使你从来没有写过任何 C 语言的代码,你也必须处理 C 语言的变量,匹配 C 语言的数据结构和布局,用符号链接 C 语言的函数名称。

消息来源:The Register
老王点评:一种有趣的思考,或许是应该思考抛弃 C 语言构建的计算世界是什么样子的了。

百度以每年 10 万的价格出租的“虚拟人”

百度表示,自去年以来,它为客户做的虚拟人项目数量翻了一番,虚拟人的一些买家包括金融服务公司、地方旅游局和媒体。百度说,随着技术的改进,自去年以来,成本已经下降了约 80%。一个三维虚拟人每年将花费约为 10 万元,一个二维虚拟人则为 2 万元。预计到 2025 年,虚拟人产业总体上将保持每年 50% 的增长。

消息来源:CNBC
老王点评:至少有一个好处是,不必担心艺人丑闻了。

美国结束 3G 网络服务

Verizon 正在告诉客户,如果他们仍在使用不支持其较新网络技术的 3G CDMA 手机,“线路将被暂停而不计费,并将失去打电话、发短信或使用数据的能力”。Verizon 是美国三大无线运营商中最后一个关闭 3G 网络并将频谱重新用于更新技术的运营商。AT&T 和 T-Mobile 已于 2022 年分别关闭了其 3G 网络。事实上,Verizon 已经几次推迟了其 3G 网络的关闭。

消息来源:Fierce Wireless
老王点评:3G 都要被抛弃了,感觉 3G 还是昨天。

我相信几乎所有的 Linux 用户都会保持他们系统的更新。

但这种更新通常是针对默认的 包管理器。例如,更新 Ubuntu 往往意味着更新所有的 APT 软件包。

然而,还有其他的打包格式,如 Snap 和 Flatpak。Snap 应用程序会自动更新,但 Flatpak 不会。

那么你如何更新 Flatpak 软件包呢?好吧,你可以用这个命令来更新所有已安装和可更新的 Flatpak 包:

flatpak update

这很简单。但让我再讨论一下关于更新 Flatpak 的一些事情,比如说:

  • 更新所有或特定的 Flatpak 包
  • 通过软件中心更新 Flatpak 包

让我们先从终端的方法开始。

方法 1:使用终端来更新 Flatpak 包

首先让我从最实用的方法开始,你也应该从这个方法开始。

更新每一个过时的 Flatpak 包

更新现有的 Flatpak 包的整个目录是很容易的。

输入给定的命令,就可以得到过期包的列表:

flatpak update

update flatpak packages in linux

你只需输入 Y 并按下回车键,就能搞定每一个更新。

更新特定的 Flatpak 包

要更新特定的软件包,你需要可以更新的软件包的列表。你用的是你之前看到的那个命令。

flatpak update

update flatpak packages in linux

从输出中复制你要更新的软件包的名称。在以下命令中使用软件包的名称:

flatpak update package_name

例如,如果你想更新 Telegram,下面的命令可以完成这项工作:

flatpak update org.telegram.desktop

update specific package in flatpak

这就完成了。

方法 2:从软件中心更新 Flatpak 应用

有 Flatpak 内置支持的发行版会在软件中心提供 Flatpak 应用的更新。Fedora 和 Linux Mint 就是这样的发行版。

但如果你使用的是 Ubuntu,你就需要在 GNOME 软件中心添加 Flatpak 支持:

sudo apt install gnome-software-plugin-flatpak

完成后,你将在 Ubuntu 中拥有两个软件中心。这是因为默认的软件中心不是 GNOME 的,而是 Snap Store。

从系统菜单中打开这个新的软件中心:

open software center in ubuntu

进入“ 更新 Update ”页面,你会发现过时的软件包列表。这包括 APT 和 Flatpak 软件包。

update flatpak from software center

在这里,你可以一次更新所有的软件包,或者你可以有选择地更新什么。

总结

许多 Linux 桌面用户往往忘记更新 Flatpak 软件包,因为它们不包括在定期的系统更新中。

由于 Flatpak 是一个沙盒式的打包解决方案,你可能不会面临任何与过时的软件包有关的问题,但你肯定会错过新的功能和修复。

这就是为什么我建议每隔几周运行一次 Flatpak 更新命令。

我希望你喜欢这个快速的 Flatpak 小技巧。


via: https://itsfoss.com/update-flatpak/

作者:Sagar Sharma 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在这篇文章中,我回顾了 2022 年最好的 Linux 发行版 —— 而剧透一下:它们并不都是基于 Ubuntu 的!

我知道:我每年都会开这样的玩笑。但是,嘿:我写的是 Ubuntu。我使用 Ubuntu。你可能希望我把所有的东西都放在 Ubuntu 上。但是 Linux 生态系统呢?它不仅仅是 Ubuntu。有很多顶级的 Linux 发行版都值得赞扬、庆祝和认可。这个名单是我给它们的一个小表扬。

也就是说,下面的内容并不代表着优越性,也不代表着重要性的排名。这只是我个人对今年的一些最好的 Linux 版本表示赞许。它是全面的吗?它也不是一个评比,所以如果你喜欢的操作系统没有出现在下面,并不是因为我认为它很糟糕!这只是我的个人观点。

随着 SEO 之神(希望)对这些冗长的介绍感到满意,让我们来看看我的 2022 年五大 Linux 发行版吧!

1、Ubuntu 22.04 LTS

a screenshot of ubuntu 22.04 desktop

对我来说,2022 年最好的 Linux 发行版可以说是 Ubuntu 22.04 LTS,它早在 4 月份就已经到来。

长期支持版本总是大事,因为有数千万人使用它们。值得庆幸的是,Ubuntu 的专业开发者推出了一个值得关注的版本。

撇开 Snap 的问题不说,Jammy Jellyfish 采用了GNOME Shell 42、可配置的强调色、默认使用 Wayland、新的多任务选项、新的停靠区选项、更好的桌面图标扩展、Linux 内核 5.15、支持树莓派 4,再加上成堆的更新的应用、工具和软件包。

虽然我是一个喜欢尝试短期版本的人 —— 一直都是,可能永远都会是 —— 但大多数人都坚持使用 LTS 版本。在 Ubuntu 22.04 中,他们得到了一个真正足够好的版本,可以在其支持期内使用,而且 没有恐惧感

2、Fedora Workstation 37

A desktop screenshot of Fedora 37 Workstation with the Settings app and Nautilus file manager open

Fedora Workstation 成为桌面 Linux 旗舰发行版是有原因的:它很强大、很可靠,制作无懈可击 —— 它提炼了很多人最想追求的东西:“纯粹” 的 GNOME 体验,并且按照开发者的意图,在一个强大而稳定的基础上提供。

秋季提供的 Fedora 37 Workstation 带有 GNOME 43 —— 一个通过 快速设置 Quick Settings 大大改善 GNOME Shell 用户体验的更新。还有一个用 GTK4/libadwaita 重建的功能更丰富的 “ 文件 Files ” 应用;一个改进的“ 日历 Calendar ”应用;一个设备安全面板;对树莓派 4 的支持;GRUB 代替了 BIOS 上的 syslinux;以及更多。

人们经常忽略 Fedora Workstation,因为作为 Linux 发行版,它相当低调,不显眼,而且没有惊喜。然而,它是一个精巧而实用的发行版,放弃了花哨的装饰,完全专注于它的性能、集成度和凝聚力。

如果你从来没有尝试过 Fedora,你就错过了,所以请试试吧!

3、Manjaro 22.0 “Sikaris”

a screenshot of the Manjaro Linux distribution with a terminal and web browser open

很明显,Manjaro 的一个版本必须出现在这个列表中。而作为基于 Arch 的 Linux 发行版,Manjaro 是最好的 Linux 发行版之一。哦,我知道:在更广泛的 Linux 社区中,围绕着 Manjaro 有很多争论,但对我来说,这些茶杯中的风暴从未影响到该发行版本身的质量(或者应该是味道 ☕️)。

12 月发布的 Manjaro 22.0 版本就是这样的例子。带有 KDE Plasma 的 “主” 分支版提供了一个完美的体验。从 Shell 到包管理器,再到定制的触摸动作和应用程序,一切都很有凝聚力,经过深思熟虑,并经过精心编排。

Manjaro 22.0 不仅仅是一个发行版,它是一种体验。

Manjaro 的特定桌面 “版本” 也组织得非常好。它们从不觉得自己是 Manjaro 加 Xfce、加 GNOME,等等。每一个版本都是精心策划的,并且漂亮地整合了各自桌面的优势 —— 或者用不太华丽的术语来说:无论你选择哪一个 Manjaro 版本,你都感觉它是“主”分支版。

另外,Manjaro 社区很大,很活跃。对于任何出现的问题,我都能在 Manjaro 论坛上找到关于它的帖子(或者有人愿意为我指出解决方案的方向)。社区是发行版的重要方面。Linux 内核是大多数发行版的核心,但社区才是其生命线。

Manjaro 是一个完整包装,绝对是年度发行版。

4、Linux Mint 21

a desktop screenshot of Linux Mint 21.1 with new folder icons showing in the Nemo file manager

Linux Mint 21.1 稍微新一些,在视觉上有些有趣的更新(比如新的小程序和更新的艺术设计),在这两个版本中,最初的 Linux Mint 21 版本在今年带来的影响更大。

作为经常被宣传的 “新手” 发行版,Linux Mint 的核心目标是提供一种轻巧和熟悉的计算体验,并保持不受影响,这一点继续得到了与 Windows 工作方式相适应的用户的共鸣。

Linux Mint 21 “Cinnamon” 是轻量级和高效的,使它成为低端硬件和旧机器上的一个很好的选择。除了易于使用之外,Linux Mint 还提供了有趣的预装软件,旨在满足大多数用户的需求,包括一些相当特别的 自制应用程序

总的来说,Linux Mint 21 是想要一个可靠和易于使用的操作系统的用户的完美选择。

5、Ubuntu 22.10

一个列表中出现了两次 Ubuntu?这有点多,但 PipeWire 的加入意味着我应该选择 22.10。说实话,这是我作为本网站编辑的义务 —— 什么? 是的,我自己写的合同……你为什么这么问?

不过说真的,Ubuntu 22.10 的上述 PipeWire 的加入(虽然已经逾期)意味着大多数蓝牙音频设备现在都能在 Ubuntu 上 “正常工作”。再加上 GNOME 的 “ 快速设置 Quick Settings ” 中的音频设备切换器,意味着 Ubuntu 22.10 在现代音频设备上的表现是正确的。

其次,GNOME 43 和一连串 libadwaita 移植的上线意味着 “Kinetic Kudu” 的出现具有真正的活力 —— 就其背景而言,它是最早尝试 GNOME 43 的方式之一 —— 这一点从早期的 Unity 时代就已经消失了。

最后,毫无疑问,最重要的、最关键的和决定性的元素是 “Kinetic Kudu” 吉祥物墙纸 —— 这是自 “Hardy Heron” 以来最好的 Ubuntu 默认墙纸,我认为。

荣誉提名

将我的选择限制在 5 个是必要的,否则这将是一个非常长的列表,需要列出在过去 12 个月中推出的每一个 Linux 发行版。

一些额外的呼声是:最近 EndeavourOS 的 “Cassini” 版本对于任何想要使用可靠的滚动发行版的人来说是一个理想的跳板。最新的 Zorin OS 是基于较早的 Ubuntu 基础上的,但开箱即用的特点对于刚接触 Linux 的用户来说仍然是令人振奋的。

游戏玩家、程序员和创作者都很喜欢 Pop!\_OS 22.04,这是 System76 发行版的最新版本,默认搭载 GNOME Shell;轻量级 Linux 发行版 MX Linux 也受到了很多人的喜爱,它为旧硬件注入了新的活力。

还有一个值得一提的就是 SteamOS,Valve 在 Steam Deck 掌机上预装的基于 Arch 的发行版。

该你了

这就是我列出的 2022 年最佳桌面 Linux 发行版。在选择它们时,我试图权衡各种功能集、变化和关键技术,并牢记其吸引力和受欢迎程度。顺便说一下,MX Linux 差一点就能占到一席之地 —— 希望能听到更多关于这个和其他发行版的消息。

总之,谁会在乎我怎么想呢?

我想听听你在过去 12 个月里对发行版的选择。所以,请在评论中写下你的看法(以及提示,比如:“老式” Disqus 主题又可以在选项中选择了,耶)。尽量保持积极的态度,把重点放在你喜欢的发行版和发展上,而不是你不喜欢的那些。

美法院称,保险不包括对软件的勒索软件攻击

美国俄亥俄州最高法院一致推翻了俄亥俄州第二区上诉法院的判决,并提出必须在公司的计算机软件中存在 “直接” 的物理损失或物理损坏,才能获得保险单的保障。法院的理由是:计算机可能有 “有形” 的电子部件,但储存在那里的信息没有 “实体存在”;因此,对公司软件的勒索软件攻击在公司的保险单下没有保障。

消息来源:Slashdot
老王点评:总觉得这个裁决有点不对劲。

台积电开始量产 3 纳米芯片

台积电在台南科学园 Fab 18 工厂举行的仪式上正式宣布量产 3 纳米芯片。相比 5 纳米芯片,3 纳米芯片逻辑晶体管密度增加 60%,功耗降低 30% 至 35%。台积电的 Fab 18 是其生产 5 纳米和 3 纳米芯片的主要基地,该设施的总投资将达到 600 多亿美元。

消息来源:Solidot
老王点评:终究还是“台积电”。

软件工程师称受电影启发盗取公司帐户的钱

1999 年上映的黑色喜剧片《Office Space》讲述了员工在银行系统中植入病毒,将每笔金融交易中的几分钱转移其帐户的故事。而现实中,一位程序员称他受该电影的启发,制定了一个计划从雇主的帐户里偷钱。他编写了软件,操纵了结账页面,将每笔交易的运费转移到个人帐户。法庭文件称他盗取了 26 万美元的运费。警方还在他的笔记本电脑里找到了名叫《OfficeSpace project》的文件,其中概述了他通过操纵审计日志和禁用告警日志清理证据的计划。

消息来源:Komonews
老王点评:不但故事来自现实,现实也会来自故事啊。

使用 C 扩展为 Python 提供特定功能。

在前一篇文章中,我介绍了 六个 Python 解释器。在大多数系统上,CPython 是默认的解释器,而且根据民意调查显示,它还是最流行的解释器。Cpython 的独有功能是使用扩展 API 用 C 语言编写 Python 模块。用 C 语言编写 Python 模块允许你将计算密集型代码转移到 C,同时保留 Python 的易用性。

在本文中,我将向你展示如何编写一个 C++ 扩展模块。使用 C++ 而不是 C,因为大多数编译器通常都能理解这两种语言。我必须提前说明缺点:以这种方式构建的 Python 模块不能移植到其他解释器中。它们只与 CPython 解释器配合工作。因此,如果你正在寻找一种可移植性更好的与 C 语言模块交互的方式,考虑下使用 ctypes 模块。

源代码

和往常一样,你可以在 GitHub 上找到相关的源代码。仓库中的 C++ 文件有以下用途:

  • my_py_module.cpp: Python 模块 MyModule 的定义
  • my_cpp_class.h: 一个头文件 - 只有一个暴露给 Python 的 C++ 类
  • my_class_py_type.h/cpp: Python 形式的 C++ 类
  • pydbg.cpp: 用于调试的单独应用程序

本文构建的 Python 模块不会有任何实际用途,但它是一个很好的示例。

构建模块

在查看源代码之前,你可以检查它是否能在你的系统上编译。我使用 CMake 来创建构建的配置信息,因此你的系统上必须安装 CMake。为了配置和构建这个模块,可以让 Python 去执行这个过程:

$ python3 setup.py build

或者手动执行:

$ cmake -B build
$ cmake --build build

之后,在 /build 子目录下你会有一个名为 MyModule. so 的文件。

定义扩展模块

首先,看一下 my_py_module.cpp 文件,尤其是 PyInit_MyModule 函数:

PyMODINIT_FUNC
PyInit_MyModule(void) {
    PyObject* module = PyModule_Create(&my_module);
    
    PyObject *myclass = PyType_FromSpec(&spec_myclass);
    if (myclass == NULL){
        return NULL;
    }
    Py_INCREF(myclass);
    
    if(PyModule_AddObject(module, "MyClass", myclass) < 0){
        Py_DECREF(myclass);
        Py_DECREF(module);
        return NULL;
    }
    return module;
}

这是本例中最重要的代码,因为它是 CPython 的入口点。一般来说,当一个 Python C 扩展被编译并作为共享对象二进制文件提供时,CPython 会在同名二进制文件中(<ModuleName>.so)搜索 PyInit_<ModuleName> 函数,并在试图导入时执行它。

无论是声明还是实例,所有 Python 类型都是 PyObject 的一个指针。在此函数的第一部分中,module 通过 PyModule_Create(...) 创建的。正如你在 module 详述(my_py_module,同名文件)中看到的,它没有任何特殊的功能。

之后,调用 PyType\_FromSpec 为自定义类型 MyClass 创建一个 Python 堆类型 定义。一个堆类型对应于一个 Python 类,然后将它赋值给 MyModule 模块。

注意,如果其中一个函数返回失败,则必须减少以前创建的复制对象的引用计数,以便解释器删除它们。

指定 Python 类型

MyClass 详述在 my\_class\_py\_type.h 中可以找到,它作为 PyType\_Spec 的一个实例:

static PyType_Spec spec_myclass = {
    "MyClass",                                  // name
    sizeof(MyClassObject) + sizeof(MyClass),    // basicsize
    0,                                          // itemsize
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   // flags
    MyClass_slots                               // slots
};

它定义了一些基本类型信息,它的大小包括 Python 表示的大小(MyClassObject)和普通 C++ 类的大小(MyClass)。MyClassObject 定义如下:

typedef struct {
    PyObject_HEAD
    int         m_value;
    MyClass*    m_myclass;
} MyClassObject;

Python 表示的话就是 PyObject 类型,由 PyObject_HEAD 宏和其他一些成员定义。成员 m_value 视为普通类成员,而成员 m_myclass 只能在 C++ 代码内部访问。

PyType\_Slot 定义了一些其他功能:

static PyType_Slot MyClass_slots[] = {
    {Py_tp_new,     (void*)MyClass_new},
    {Py_tp_init,    (void*)MyClass_init},
    {Py_tp_dealloc, (void*)MyClass_Dealloc},
    {Py_tp_members, MyClass_members},
    {Py_tp_methods, MyClass_methods},
    {0, 0} /* Sentinel */
};

在这里,设置了一些初始化和析构函数的跳转,还有普通的类方法和成员,还可以设置其他功能,如分配初始属性字典,但这是可选的。这些定义通常以一个哨兵结束,包含 NULL 值。

要完成类型详述,还包括下面的方法和成员表:

static PyMethodDef MyClass_methods[] = {
    {"addOne", (PyCFunction)MyClass_addOne, METH_NOARGS,  PyDoc_STR("Return an incrmented integer")},
    {NULL, NULL} /* Sentinel */
};

static struct PyMemberDef MyClass_members[] = {
    {"value", T_INT, offsetof(MyClassObject, m_value)},
    {NULL} /* Sentinel */
};

在方法表中,定义了 Python 方法 addOne,它指向相关的 C++ 函数 MyClass_addOne。它充当了一个包装器,它在 C++ 类中调用 addOne() 方法。

在成员表中,只有一个为演示目的而定义的成员。不幸的是,在 PyMemberDef 中使用的 offsetof 不允许添加 C++ 类型到 MyClassObject。如果你试图放置一些 C++ 类型的容器(如 std::optional),编译器会抱怨一些内存布局相关的警告。

初始化和析构

MyClass_new 方法只为 MyClassObject 提供一些初始值,并为其类型分配内存:

PyObject *MyClass_new(PyTypeObject *type, PyObject *args, PyObject *kwds){
    std::cout << "MtClass_new() called!" << std::endl;

    MyClassObject *self;
    self = (MyClassObject*) type->tp_alloc(type, 0);
    if(self != NULL){ // -> 分配成功
        // 赋初始值
        self->m_value   = 0;
        self->m_myclass = NULL; 
    }
    return (PyObject*) self;
}

实际的初始化发生在 MyClass_init 中,它对应于 Python 中的 \_\_init\_\_() 方法:

int MyClass_init(PyObject *self, PyObject *args, PyObject *kwds){
    
    ((MyClassObject *)self)->m_value = 123;
    
    MyClassObject* m = (MyClassObject*)self;
    m->m_myclass = (MyClass*)PyObject_Malloc(sizeof(MyClass));

    if(!m->m_myclass){
        PyErr_SetString(PyExc_RuntimeError, "Memory allocation failed");
        return -1;
    }

    try {
        new (m->m_myclass) MyClass();
    } catch (const std::exception& ex) {
        PyObject_Free(m->m_myclass);
        m->m_myclass = NULL;
        m->m_value   = 0;
        PyErr_SetString(PyExc_RuntimeError, ex.what());
        return -1;
    } catch(...) {
        PyObject_Free(m->m_myclass);
        m->m_myclass = NULL;
        m->m_value   = 0;
        PyErr_SetString(PyExc_RuntimeError, "Initialization failed");
        return -1;
    }

    return 0;
}

如果你想在初始化过程中传递参数,必须在此时调用 PyArg\_ParseTuple。简单起见,本例将忽略初始化过程中传递的所有参数。在函数的第一部分中,PyObject 指针(self)被强转为 MyClassObject 类型的指针,以便访问其他成员。此外,还分配了 C++ 类的内存,并执行了构造函数。

注意,为了防止内存泄漏,必须仔细执行异常处理和内存分配(还有释放)。当引用计数将为零时,MyClass_dealloc 函数负责释放所有相关的堆内存。在文档中有一个章节专门讲述关于 C 和 C++ 扩展的内存管理。

包装方法

从 Python 类中调用相关的 C++ 类方法很简单:

PyObject* MyClass_addOne(PyObject *self, PyObject *args){
    assert(self);

    MyClassObject* _self = reinterpret_cast<MyClassObject*>(self);
    unsigned long val = _self->m_myclass->addOne();
    return PyLong_FromUnsignedLong(val);
}

同样,PyObject 参数(self)被强转为 MyClassObject 类型以便访问 m_myclass,它指向 C++ 对应类实例的指针。有了这些信息,调用 addOne() 类方法,并且结果以 Python 整数对象 返回。

3 种方法调试

出于调试目的,在调试配置中编译 CPython 解释器是很有价值的。详细描述参阅 官方文档。只要下载了预安装的解释器的其他调试符号,就可以按照下面的步骤进行操作。

GNU 调试器

当然,老式的 GNU 调试器(GDB) 也可以派上用场。源码中包含了一个 gdbinit 文件,定义了一些选项和断点,另外还有一个 gdb.sh 脚本,它会创建一个调试构建并启动一个 GDB 会话:

Gnu 调试器(GDB)对于 Python C 和 C++ 扩展非常有用

GDB 使用脚本文件 main.py 调用 CPython 解释器,它允许你轻松定义你想要使用 Python 扩展模块执行的所有操作。

C++ 应用

另一种方法是将 CPython 解释器嵌入到一个单独的 C++ 应用程序中。可以在仓库的 pydbg.cpp 文件中找到:

int main(int argc, char *argv[], char *envp[])
{
    Py_SetProgramName(L"DbgPythonCppExtension");
    Py_Initialize();

    PyObject *pmodule = PyImport_ImportModule("MyModule");
    if (!pmodule) {
        PyErr_Print();
        std::cerr << "Failed to import module MyModule" << std::endl;
        return -1;
    }

    PyObject *myClassType = PyObject_GetAttrString(pmodule, "MyClass");
    if (!myClassType) {
        std::cerr << "Unable to get type MyClass from MyModule" << std::endl;
        return -1;
    }

    PyObject *myClassInstance = PyObject_CallObject(myClassType, NULL);

    if (!myClassInstance) {
        std::cerr << "Instantioation of MyClass failed" << std::endl;
        return -1;
    }

    Py_DecRef(myClassInstance); // invoke deallocation
    return 0;
}

使用 高级接口,可以导入扩展模块并对其执行操作。它允许你在本地 IDE 环境中进行调试,还能让你更好地控制传递或来自扩展模块的变量。

缺点是创建一个额外的应用程序的成本很高。

VSCode 和 VSCodium LLDB 扩展

使用像 CodeLLDB 这样的调试器扩展可能是最方便的调试选项。仓库包含了一些 VSCode/VSCodium 的配置文件,用于构建扩展,如 task.jsonCMake Tools 和调用调试器(launch.json)。这种方法结合了前面几种方法的优点:在图形 IDE 中调试,在 Python 脚本文件中定义操作,甚至在解释器提示符中动态定义操作。

VSCodium 有一个集成的调试器。

用 C++ 扩展 Python

Python 的所有功能也可以从 C 或 C++ 扩展中获得。虽然用 Python 写代码通常认为是一件容易的事情,但用 C 或 C++ 扩展 Python 代码是一件痛苦的事情。另一方面,虽然原生 Python 代码比 C++ 慢,但 C 或 C++ 扩展可以将计算密集型任务提升到原生机器码的速度。

你还必须考虑 ABI 的使用。稳定的 ABI 提供了一种方法来保持旧版本 CPython 的向后兼容性,如 文档 所述。

最后,你必须自己权衡利弊。如果你决定使用 C 语言来扩展 Python 中的一些功能,你已经看到了如何实现它。


via: https://opensource.com/article/22/11/extend-c-python

作者:Stephan Avenwedde 选题:lkxed 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这个 Linux 文件管理器做了你所期望的一切,没有留下不愉快的惊喜。但这里有一些令人惊喜的事情,使它值得一试。

QtFM 是一个简单的文件管理器,旨在通过一个快速直观的界面提供文件管理的基本功能。它适用于 Linux、BSD 和 macOS。

QtFM,顾名思义,使用 Qt(规范发音为 “cute”)编程工具包。我在 C++ 和 Python 中使用过 Qt 工具包,使用它总是一种乐趣。它是跨平台的,具有多个有用的抽象级别,因此开发人员不必直接与特定于供应商的 SDK 交互,而且它具有高度可配置性。从用户的角度来看,无论你使用的是最新的硬件还是旧计算机,这都是一种“自然”且快速的体验。

使用 QtFM

QtFM 没有太多内容。它专注于实现其名称所声称的:Qt 的文件管理器(FM)。其布局可能是你对文件管理器的期望:左侧是常用位置和设备的列表,右侧是文件列表。

QtFM file manager

它只有四个菜单:

  • 文件 File :创建新文件或文件夹,打开新选项卡或窗口,或退出应用。
  • 编辑 Edit :在左侧面板中复制、粘贴、移至垃圾箱或创建新书签。
  • 视图 View :在列表视图和图标视图之间切换,调整布局。
  • 帮助 Help :许可信息和在线文档链接。

与 QtFM 交互与你可能习惯使用的任何标准文件管理器的体验大致相同。你可以点击导航、在其默认应用中打开文件、拖放文件和文件夹、复制和粘贴文件和文件夹、启动应用,以及你在与计算机内容交互时执行的任何其他操作。它很熟悉,所以基本上没有学习曲线,也没有不愉快的惊喜。

然而,也有一些惊喜。这是我最喜欢的三个。

1、将命令放入上下文菜单

使用 QtFM,你可以将可以在终端中运行的任何命令添加到右键单击上下文菜单中。例如,假设你想要一个将图像转换为 webp 格式 的选项到右键菜单。无需学习复杂的框架或脚本语言,无需开发插件。你只需 3 个步骤即可完成:

  • 转到 “ 编辑 Edit ” 菜单并选择 “ 设置 Settings ”。
  • 单击 “ 自定义操作选项卡 Custom actions tab ”。
  • 单击 “ 添加 Add ” 按钮并输入要运行的命令,用 %f 代表源文件,用 %n 代表新文件。

QtFM custom actions

该操作现在出现在你的 QtFM 上下文菜单中。

2、灵活的布局

Qt 工具包的内置功能之一是它的许多组件(“小部件”)是可分离的。QtFM 利用了这一点,并允许你从 “ 视图 View ” 菜单中解锁其布局。解锁后,你可以拖动工具栏和侧面板,将它们固定在窗口周围的新位置。我能够将菜单栏、导航工具栏和 URI 字段组合到一个统一的面板中,并且为了方便,我在窗口的右侧放置了一个文件树。

QtFM unlocking the layout

这不需要应用设计甚至配置的特殊知识。你只需解锁、拖放和锁定。

3、标签视图

许多 Linux 文件管理器提供选项卡的方式与大多数 Web 浏览器相同。这是一个简单的界面技巧,可让你方便地保留多个位置。我不知道它是否真的节省了时间,但我总觉得它确实如此。QtFM 也提供选项卡,我特别喜欢它实现选项卡的方式有两点。

首先,选项卡默认位于窗口底部(你可以在 “ 设置 Settings ” 中更改它)。因为我倾向于从左到右、从上到下阅读,所以我通常更喜欢在窗口的底部和右端设置“额外”信息。当然,“额外”信息的构成因用户而异,因此我不会责怪任何开发人员将小部件和面板放置在我不会放置小部件和面板的地方。不过,当开发人员不小心同意我的偏好时,这很好。

其次,标签是响应式的。只需将鼠标悬停在目标选项卡上,即可将文件或文件夹从一个选项卡拖动到另一个选项卡中。感觉就像从一个窗口拖放到另一个窗口一样自然。

安装 QtFM

在 Linux 上,你的发行版可能会将 QtFM 打包在它的软件仓库中。如果是这样,你可以使用包管理器进行安装。例如,在 Debian 和基于 Debian 的系统上:

$ sudo apt install qtfm

如果你的发行版不提供 QtFM,你可以在其 网站 上找到它的软件包,或者你可以从它的 Git 仓库 下载源码。


via: https://opensource.com/article/22/12/linux-file-manager-qtfm

作者:Seth Kenlon 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux 中国 荣誉推出