You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Python获取ctypes调用C函数的传入与返回指针值?

如何用Python+ctypes获取C函数的传入/返回指针值并做pytest验证

我需要通过Python调用C共享库函数时,拿到传入和返回的实际C层指针值,用pytest验证函数的内存分配逻辑——比如验证strdup返回的是新内存地址的指针,而非原指针。

踩过的坑

  • 直接用Python的id()函数完全没用:它返回的是Python对象在解释器里的地址,和C层实际指针无关;而且空字节对象有复用优化,不同对象可能返回相同地址,根本没法用来做可靠验证。
  • 把C函数的restype设为ctypes.c_void_p能拿到返回的指针值,但没法获取传给C函数的传入指针的实际地址。

解决方案

用ctypes.create_string_buffer创建缓冲区,结合ctypes.addressof和指针类型转换,就能同时拿到传入和返回的真实C指针值,完美解决验证需求。

测试代码示例

import ctypes
import pytest

# 加载系统C库(Windows下替换为"msvcrt.dll")
libc = ctypes.CDLL("libc.so.6")

# 明确strdup的参数和返回类型,避免ctypes默认转换的坑
libc.strdup.argtypes = (ctypes.c_char_p,)
libc.strdup.restype = ctypes.c_void_p

def test_strdup_allocates_new_memory():
    # 创建带初始内容的缓冲区,避开空对象复用的问题
    original_buffer = ctypes.create_string_buffer(b"hello world")
    # 获取传给C函数的实际指针地址
    original_ptr = ctypes.addressof(original_buffer)
    
    # 调用strdup复制字符串
    duplicated_ptr = libc.strdup(original_buffer)
    
    # 核心验证:返回的指针必须和原指针不同,说明分配了新内存
    assert duplicated_ptr != original_ptr
    
    # 清理:释放strdup分配的内存,避免泄漏
    libc.free(duplicated_ptr)

关键说明

  • create_string_buffer创建的是C风格的字符数组缓冲区,它的底层内存地址就是直接传给C函数的指针,用ctypes.addressof可以直接获取这个真实的C指针值。
  • 给C函数指定argtypes和restype是好习惯,能避免ctypes自动类型转换带来的潜在问题,这里把restype设为c_void_p,就能直接拿到返回的原始指针地址。
  • 测试完成后一定要调用free释放内存,尤其是在循环测试场景下,避免内存泄漏累积。

内容的提问来源于stack exchange,提问作者vmonteco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 22:58:15