如何在 Python 中调用 .so 文件中的方法

发布时间: 更新时间: 总字数:1121 阅读时间:3m 作者: IP上海 分享 网址

在 Python 中调用 .so(共享库,Linux 下的动态链接库)文件中的方法,主要依赖于 Python 的标准库 ctypesctypes 提供了与 C 语言兼容的数据类型和函数,允许 Python 代码直接调用动态链接库中的函数。本文介绍详细的步骤和示例。

1. 准备 .so 文件

首先,需要一个 .so 文件。通常,这个文件是用 C 或 C++ 编写并编译而成的。

示例 C 代码 (mylib.c):

#include <stdio.h>

// 一个简单的加法函数
int add(int a, int b) {
    return a + b;
}

// 一个打印问候语的函数
void greet(const char* name) {
    printf("Hello, %s!\n", name);
}

编译 C 代码生成 .so 文件:

在 Linux 系统中,可以使用 GCC 编译上述代码:

gcc -shared -o mylib.so mylib.c

这会生成一个名为 mylib.so 的共享库文件。

2. 使用 ctypes 调用 .so 文件

接下来,我们将使用 Python 的 ctypes 库来加载并调用 mylib.so 中的函数。

import ctypes
import os

# 1. 加载 .so 文件
# 确保 mylib.so 文件与你的 Python 脚本在同一个目录下,
# 或者提供完整的路径。
current_dir = os.path.dirname(os.path.abspath(__file__))
lib_path = os.path.join(current_dir, 'mylib.so')

try:
    my_lib = ctypes.CDLL(lib_path)
except OSError as e:
    print(f"Error loading library: {e}")
    print("Please ensure 'mylib.so' is in the same directory as this script or provide the full path.")
    exit()

# 2. 调用 add 函数
# 默认情况下,ctypes 假定函数返回 int 类型,并且参数是 int 类型。
# 但是,为了明确和避免潜在错误,最好显式指定参数类型和返回类型。

# 设置 add 函数的参数类型和返回类型
my_lib.add.argtypes = [ctypes.c_int, ctypes.c_int]
my_lib.add.restype = ctypes.c_int

result = my_lib.add(5, 3)
print(f"5 + 3 = {result}")  # 输出: 5 + 3 = 8

# 3. 调用 greet 函数
# greet 函数接受一个字符串(C 中的 const char*)作为参数,并且没有返回值 (void)。

# 设置 greet 函数的参数类型和返回类型
# 对于字符串参数,使用 ctypes.c_char_p
# 对于 void 返回值,restype 不需要设置或设置为 None
my_lib.greet.argtypes = [ctypes.c_char_p]
my_lib.greet.restype = None  # 或者不设置这行

# Python 字符串需要编码为字节串 (bytes) 才能传递给 C 函数
name = "Pythonista"
my_lib.greet(name.encode('utf-8')) # 输出: Hello, Pythonista!

# 尝试调用不存在的函数(会报错)
# try:
#     my_lib.non_existent_function()
# except AttributeError as e:
#     print(f"\nError: {e}")

关键概念和注意事项:

  • ctypes.CDLLctypes.CDLL (Windows): 用于加载共享库。
    • ctypes.CDLL 用于调用遵循标准 C 调用约定(__cdecl)的库。
    • ctypes.CDLL 用于调用遵循 __stdcall 调用约定的库(在 Windows 上常见)。
  • argtypes: 一个列表,用于指定 C 函数的参数类型。Python 会自动将 Python 类型转换为相应的 C 类型。
    • ctypes.c_int: C int
    • ctypes.c_float: C float
    • ctypes.c_double: C double
    • ctypes.c_char_p: C char* (字符串,需要传入字节串)
    • ctypes.c_void_p: C void* (通用指针)
    • ctypes.POINTER(ctypes.c_int): 指向 int 的指针
    • 更多类型请参考 ctypes 文档。
  • restype: 指定 C 函数的返回值类型。如果不设置,ctypes 默认假定返回 int。如果 C 函数返回 void,可以将其设置为 None 或不设置。
  • 字符串处理: C 函数通常期望 char*const char* 类型的字符串。在 Python 中,你需要将字符串编码为字节串 (.encode('utf-8')) 传递给 C 函数。
  • 错误处理: 如果 .so 文件不存在或路径不正确,ctypes.CDLL 会抛出 OSError。如果调用的函数不存在,会抛出 AttributeError
  • 复杂数据结构: 对于更复杂的数据结构(如结构体、数组),ctypes 提供了 ctypes.Structurectypes.Union 和数组类型 (ctypes.c_int * 10) 来进行映射。

通过 ctypes,Python 可以有效地与用其他语言编写的动态链接库进行交互,从而扩展其功能或利用现有高性能库。

本文总阅读量 次 本站总访问量 次 本站总访客数
Home Archives Categories Tags Statistics