在Python退出时,如何调用.pyd库中的一个函数?

编程语言 2026-07-12

我正在把一个小型的Python库用C++开发作为一个项目,使用MiniAudio来制作一个合成器,并用Pybind11与 CMake构建一个.pyd文件。

我已经设法避免把我的库做成一个庞大的类,但这意味着没有构造函数和析构函数。对于音频库,我想在导入时初始化设备、通道等——这通过把我的初始化函数添加到我的 PYBIND11_MODULE 函数中实现。

然而,我不确定如何让一个函数在退出时也运行。尽管这可能没问题,因为我的 uninit() 函数只是做内存清理,但把这件事交给用户来调用似乎是个坏做法,因为如果用户只是要关闭Python,几乎没有理由让他们去执行它。

我在想是否有些什么巧妙的变通方法,不需要把整套东西打包成一个类(出于安全性和速度方面的原因)。我在努力让运行时尽可能顺畅,以便在中低端硬件上也能良好运行。

解决方案

既然你想避免把所有内容包装成一个庞大的类,Pybind11 里有一个高效的内置模块,名为 py::capsule

Pybind11 中,你可以给你的模块附加一个不透明指针,也就是所谓的 capsule。当Python退出或你的模块被 垃圾回收,它会自动销毁这个capsule。通过给这个capsule附加一个自定义的C++析构函数,你可以在退出时自动触发你的 uninit() 函数。

以下是你可以采用的一般做法,

#include <pybind11/pybind11.h>

namespace py = pybind11;

// Your existing functions
void init() {
    // Initialize MiniAudio devices, channels, etc.
}

void uninit() {
    // Cleanup memory, close audio streams and release devices
}

PYBIND11_MODULE(my_audio_lib, m) {
    m.doc() = "A fast Python synthesizer library using MiniAudio";

    // 1. Run initialization immediately on import
    init();

    // 2. Register the cleanup function to run on module unload/exit
    m.add_object("_cleanup", py::capsule((void*)nullptr, [](void*) {
        uninit();
    }));

    // 3. Bind your actual library functions below
    m.def("play_sound", &some_play_function, "Plays a sound");
    // ....
}

注意:音频线程注意事项

因为 uninit() 会在Python解释器关闭阶段被触发,你需要确保在释放内存之前,你的 uninit() 函数强制将任何MiniAudio产生的后台C++音频线程join进来,或将其终止。如果在Python解释器关闭时,一个C++音频线程仍在尝试从内存读取数据,退出时将导致严重的段错误。

希望对你有帮助!

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章