如何通过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
相关产品推荐
相关产品推荐

