Python 打包成动态链接库(DLL)

Python 是一种广泛使用的编程语言,因其简洁的语法和强大的库而受到许多开发者的青睐。然而,在某些情况下,我们可能希望将 Python 代码打包成动态链接库(DLL),从而使其他语言(如 C/C++、C# 等)能够直接使用这些 Python 功能。本文将带您了解如何将 Python 代码打包成 DLL,并提供相应的代码示例。

为什么要打包成 DLL?

  1. 复用性:通过打包成 DLL,您可以在其他项目中复用您的 Python 代码,而无需重新实现相同的功能。
  2. 性能:将 Python 代码编译为机器语言并打包成 DLL,可以提高执行效率,尤其是在性能敏感的场景中。
  3. 语言互操作性:DLL 使得不同编程语言之间可以调用相同的功能,有助于构建更为复杂的系统。

打包过程概述

打包 Python 代码成 DLL 涉及几个步骤:

  1. 编写 Python 代码。
  2. 使用 ctypescffi 库创建 C 接口。
  3. 编译 Python 文件为 DLL。

下面我们将详细探讨这几个步骤。

第一步:编写 Python 代码

我们从一个简单的 Python 函数开始。假设我们编写一个用于计算两个数和的函数 add

# my_module.py
def add(x, y):
    return x + y
  • 1.
  • 2.
  • 3.
第二步:创建 C 接口

为了使其他语言能够调用我们的 Python 函数,我们需要创建一个 C 语言接口。这可以通过 ctypescffi 实现。这里我们展示 ctypes 的方法。

# interface.py
import ctypes
from my_module import add

class PyModule:
    def add(self, x, y):
        return add(x, y)

# Create a C-compatible interface
def create_interface():
    return PyModule()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
第三步:编译为 DLL

使用 setuptoolsCython 工具,我们可以将以上 Python 代码编译成 DLL。

首先,确保已经安装 Cythonsetuptools

pip install cython setuptools
  • 1.

然后,编写 setup.py 文件:

# setup.py
from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules=cythonize("interface.py"),
)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

接下来,运行以下命令进行编译:

python setup.py build_ext --inplace
  • 1.

执行后,在 directory 中会生成一个 .pyd 文件(Windows 下的 DLL 文件)。

如何在其他语言中使用 DLL

生成 DLL 后,可以在 C/C++ 中通过 ctypes 调用它。

示例代码如下:

// main.c
#include <stdio.h>
#include <dlfcn.h>

int main() {
    void *handle = dlopen("my_module.dll", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "Cannot open library: %s\n", dlerror());
        return 1;
    }

    int (*add)(int, int) = dlsym(handle, "add");
    if (!add) {
        fprintf(stderr, "Cannot load symbol 'add': %s\n", dlerror());
        return 1;
    }

    int result = add(2, 3);
    printf("Result: %d\n", result);
    
    dlclose(handle);
    return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

在 C 语言中,我们通过 dlopen 加载 DLL,然后通过 dlsym 获取函数指针,最后调用 Python 中的 add 函数。

关系图

下面是 Python 模块、C 接口和 DLL 的关系图,帮助更好地理解这几者之间的联系。

erDiagram
    PYTHON_MODULE {
        string name
        int adds(int x, int y)
    }
    
    C_INTERFACE {
        string name
        int add(int x, int y)
    }
    
    DLL {
        string name
        function add(int x, int y)
    }
    
    PYTHON_MODULE ||--o{ C_INTERFACE : implements
    C_INTERFACE ||--o{ DLL : compiles_to

结尾

通过以上步骤,您可以轻松地将 Python 代码打包成动态链接库(DLL),并在其他编程语言中使用。这种方法提升了代码的复用性和性能,是跨语言开发的一种有效手段。无论您是开发复杂的应用程序,还是需要在不同环境中共用相同的功能,将 Python 代码封装为 DLL 都是值得尝试的解决方案。希望这篇文章能够帮助您更好地理解 Python DLL 打包的过程,并在实际项目中得以应用。