小能豆

如何使用python将数据设置为共享库中的全局变量

py

我有一个共享库 (DLL),我正在将其导入到 Python 脚本中,我可以调用函数,但无法写入全局变量。我使用“memset”传递全局变量的地址、数据和变量的大小(在这种情况下为 4 个字节,因为该全局变量是一个整数),但当我尝试读取全局变量时,它总是显示输出为 0(零)。有人能帮我吗?如何使用 Python 将数据设置为共享库中的全局变量?


阅读 7

收藏
2024-12-23

共1个答案

小能豆

在使用 Python 调用共享库(DLL)时,正确处理全局变量需要确保你正在正确地访问和修改共享库中的内存。由于共享库中的全局变量是在库加载时初始化的,你必须正确地将它们传递给 Python 并确保它们的数据更新。

关键问题

你提到尝试使用 memset 来修改全局变量,但 memset 只会填充内存并将数据清零,而无法像你所期望的那样修改共享库中的全局变量。要在 Python 中成功地修改共享库的全局变量,你需要确保以下几点:

  1. 确保正确传递指针地址:Python 需要能够访问共享库中的变量地址,并且能够通过该地址修改数据。
  2. 确保类型匹配:你传递给共享库的变量类型必须与 C 中定义的变量类型匹配。
  3. 使用正确的调用约定:如果你的共享库是用 C 编写的,那么你必须确保 Python 正确地调用 C 函数(使用 ctypescffi)。

使用 ctypes 修改全局变量

Python 提供了 ctypes 库来与共享库进行交互。通过 ctypes,你可以调用共享库中的函数,并直接操作内存中的全局变量。

示例:如何使用 ctypes 修改 DLL 中的全局变量

假设你有一个名为 mydll.dll 的共享库,并且其中包含一个全局变量 global_var 和一个函数 set_global_var 来修改它。

C 代码(共享库 mydll.dll)示例:
#include <stdio.h>

int global_var = 0;  // 定义一个全局变量

void set_global_var(int value) {
    global_var = value;  // 修改全局变量
}

int get_global_var() {
    return global_var;  // 获取全局变量
}

使用这个代码,编译一个共享库(例如,mydll.dll)。

Python 代码(使用 ctypes 访问全局变量):

在 Python 中,你可以使用 ctypes 库来加载 DLL,并通过传递指针直接操作全局变量。

import ctypes

# 加载 DLL
mydll = ctypes.CDLL('mydll.dll')

# 定义全局变量的数据类型(假设它是一个整数)
global_var_ptr = ctypes.pointer(ctypes.c_int(0))  # 初始化为 0

# 获取当前全局变量的值
print(f"Before: {global_var_ptr.contents.value}")

# 调用 DLL 中的 set_global_var 函数来修改全局变量
mydll.set_global_var(42)

# 获取修改后的全局变量的值
print(f"After: {global_var_ptr.contents.value}")

# 如果你有一个函数来获取全局变量的值,可以直接调用它
mydll.get_global_var.restype = ctypes.c_int  # 设置返回类型
result = mydll.get_global_var()  # 获取值
print(f"Global Var (via get): {result}")

解释:

  1. 加载 DLL:使用 ctypes.CDLL('mydll.dll') 加载共享库。
  2. 创建指针:我们创建一个指向整数的 ctypes.pointer(ctypes.c_int(0)),这将充当全局变量的代理。这个指针将在 DLL 中用来修改全局变量。
  3. 调用函数:我们调用 set_global_var 函数来设置全局变量的值。
  4. 获取全局变量的值:通过访问 global_var_ptr.contents.value 或通过调用 get_global_var 函数,来读取全局变量的值。

注意:

  • 你可以直接访问共享库中的全局变量,而不需要使用 memset
  • ctypes 会处理 C 语言中的指针,并允许你直接修改共享库中的全局变量。

常见问题及解决方法:

  1. 类型不匹配:确保在 ctypes 中创建的变量类型与你在 C 代码中定义的类型匹配。如果 global_varint,你应当使用 ctypes.c_int

  2. 指针访问问题:在访问或修改全局变量时,请确保你传递的是正确的指针。如果全局变量是一个简单的整数,可以直接通过 ctypes.pointer(ctypes.c_int(...)) 传递指针。

  3. 全局变量作用域:在 C 中,全局变量的作用域是整个程序。确保你没有错误地重新定义或覆盖了全局变量的地址。

  4. DLL 加载问题:确保你的共享库路径正确。如果你使用的是 Windows 系统,.dll 文件需要放在合适的路径下,或者使用绝对路径来加载它。

通过使用 ctypes,你可以轻松地将数据设置为共享库中的全局变量,并避免手动修改内存。

2024-12-23