当前位置:首页>python>Python模块教程:ctypes模块示例演示(用Python调用C 语言)

Python模块教程:ctypes模块示例演示(用Python调用C 语言)

  • 2026-10-11 08:33:12
Python模块教程:ctypes模块示例演示(用Python调用C 语言)

Python,速成心法

敲代码,查资料,问度娘

练习,探索,总结,优化

★★★★★博文创作不易,源码使用过程中,如有疑问的地方,欢迎大家指正留言交流。喜欢的老铁可以多多点赞+收藏分享+置顶,小红牛在此表示感谢。★★★★★

Tkinter教程40:(鼠标,键盘等)事件处理综合示例
Tkinter教程39:常用tk组件综合示例,3分钟带你速学速成,安排 !!
Matplotlib教程07:mplcursors也能实现,鼠标悬停交互显示
Python爬虫教程30:Selenium网页元素,定位的8种方法!
Python教程94:jieba模块用法(分词模式+自定义词典+提取词性+关键字),一个优秀的中文分词库。
Python入门教程11:time模块的示例用法
Python入门教程10:datetime模块的示例用法
Python入门教程21:os模块的示例用法
Python教程91:关于海龟画图,Turtle模块需要学习的知识点
Python零基础教程:小白入门自学知识点大纲

Python模块教程:difflib文本差异化比较

ctypes 是 Python 标准库中的一个外部函数接口(FFI)模块,它允许 Python 代码直接调用 C 语言编写的动态链接库(如 Windows 上的 .dll、Linux 上的 .so、macOS 上的 .dylib),并实现 Python 与 C 之间的数据类型转换。

核心功能

加载 C 库:通过 CDLL、WinDLL 等类载入动态库。
映射 C 数据类型:提供 c_int、c_char_p、c_void_p 等类型,与 C 的 int、char*、void* 对应。
定义结构体/联合体:继承 Structure / Union 并声明 _fields_ 来映射 C 的 struct / union。
调用 C 函数:自动处理参数和返回值类型转换(需设置 argtypes 和 restype 提高安全性)。
指针与引用:使用 pointer()、byref() 传递指针,实现输出参数或数组操作。
回调函数:通过 CFUNCTYPE 将 Python 函数包装成 C 函数指针,供 C 库回调。
直接操作内存:cast()、memmove、string_at 等可用于底层内存读写。

以下是一个使用 ctypes 模块的综合示例,演示了加载动态库、定义结构体、调用函数、传递指针/数组、使用回调函数等常见操作。本示例基于标准 C 库(Linux/macOS 下的 libc,Windows 下需稍作调整),可直接运行。

↓ 源码如下 ↓

# -*- coding: utf-8 -*-# @Author : 小红牛# 微信公众号:wdPythonimport ctypesimport sys# 1. 加载 C 标准库(跨平台尝试)if sys.platform == "win32":    libc = ctypes.CDLL("msvcrt.dll")   # Windows 下的 C 运行库else:    libc = ctypes.CDLL("libc.so.6")    # Linux 常用    # 若失败可尝试 libc.dylib (macOS) 或使用 ctypes.util.find_library# 2. 定义 C 结构体(对应 struct tm)class StructTm(ctypes.Structure):    _fields_ = [        ("tm_sec",   ctypes.c_int),        ("tm_min",   ctypes.c_int),        ("tm_hour",  ctypes.c_int),        ("tm_mday",  ctypes.c_int),        ("tm_mon",   ctypes.c_int),        ("tm_year",  ctypes.c_int),        ("tm_wday",  ctypes.c_int),        ("tm_yday",  ctypes.c_int),        ("tm_isdst", ctypes.c_int),    ]# 3. 设置函数参数类型和返回类型(类型安全检查)# time_t time(time_t *t)libc.time.argtypes = [ctypes.POINTER(ctypes.c_long)]libc.time.restype = ctypes.c_long# struct tm *localtime(const time_t *timep)libc.localtime.argtypes = [ctypes.POINTER(ctypes.c_long)]libc.localtime.restype = ctypes.POINTER(StructTm)# size_t strftime(char *s, size_t max, const char *format, const struct tm *tm)libc.strftime.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_char_p, ctypes.POINTER(StructTm)]libc.strftime.restype = ctypes.c_size_t# int printf(const char *format, ...) 可变参数需要特殊处理,这里只演示固定签名libc.printf.argtypes = [ctypes.c_char_p]libc.printf.restype = ctypes.c_int# 4. 调用函数示例:获取当前时间并格式化输出def demo_time():    # 调用 time(NULL) 获得时间戳    t = libc.time(None)    print(f"Raw time_t: {t}")    # 调用 localtime 转换为结构体指针    tm_ptr = libc.localtime(ctypes.byref(ctypes.c_long(t)))    # 解引用指针得到结构体内容    tm_struct = tm_ptr.contents    print(f"Current tm: {tm_struct.tm_hour}:{tm_struct.tm_min}:{tm_struct.tm_sec}")    # 使用 strftime 格式化时间字符串    buf = ctypes.create_string_buffer(100)          # 可写缓冲区    fmt = b"%Y-%m-%d %H:%M:%S"    n = libc.strftime(buf, len(buf), fmt, tm_ptr)    print(f"Formatted time: {buf.value.decode()} (length={n})")# 5. 使用数组:调用 qsort 对整数排序(回调函数演示)# 定义比较回调类型:int cmp(const void *a, const void *b)CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p)@CMPFUNCdef py_cmp(a, b):    # 将 void* 转换为 int* 并解引用    x = ctypes.cast(a, ctypes.POINTER(ctypes.c_int)).contents.value    y = ctypes.cast(b, ctypes.POINTER(ctypes.c_int)).contents.value    return x - ydef demo_qsort():    # 准备一个整数数组    IntArray5 = ctypes.c_int * 5    arr = IntArray5(42, 7, 13, 99, 5)    print("Before sort:", list(arr))    # 获取 qsort 函数(某些平台需显式声明)    libc.qsort.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_size_t, CMPFUNC]    libc.qsort.restype = None    # 调用 qsort    libc.qsort(arr, len(arr), ctypes.sizeof(ctypes.c_int), py_cmp)    print("After sort: ", list(arr))# 6. 指针和 byref 用法:修改变量值def demo_pointer():    x = ctypes.c_int(100)    print(f"Before: {x.value}")    # 假设有一个 C 函数 void add_one(int *p) { *p += 1; }    # 我们手动模拟:通过 ctypes 直接操作指针    # 注意:这里没有真实的 add_one,仅演示指针操作    ptr = ctypes.pointer(x)      # 获取 POINTER(c_int)    ptr.contents.value += 1      # 等价于 *ptr += 1    print(f"After pointer increment: {x.value}")    # 使用 byref 传递引用(更高效,通常用于函数参数)    # 例如:libc.time(ctypes.byref(t_var))# 7. 错误处理:检查函数返回值def demo_error_handling():    # 故意调用一个可能失败的函数:打开不存在的文件 (fopen)    if sys.platform != "win32":        libc.fopen.argtypes = [ctypes.c_char_p, ctypes.c_char_p]        libc.fopen.restype = ctypes.c_void_p        fp = libc.fopen(b"/nonexistent/file.txt", b"r")        if fp == 0:   # NULL 指针            print("Error: fopen failed (errno handled elsewhere)")        else:            # 正常关闭文件(演示用)            libc.fclose.argtypes = [ctypes.c_void_p]            libc.fclose(fp)    else:        print("Skipping fopen demo on Windows (uses different API)")# 运行所有示例if __name__ == "__main__":    print("=== CTime Demo ===")    demo_time()    print("\n=== QSort with Callback ===")    demo_qsort()    print("\n=== Pointer Manipulation ===")    demo_pointer()    print("\n=== Error Handling ===")    demo_error_handling()

完毕!!感谢您的收看

--------★★历史博文集合★★--------

Python入门篇  进阶篇  视频教程  Py安装

py项目Python模块 Python爬虫  Json

Xpath正则表达式SeleniumEtreeCss

Gui程序开发TkinterPyqt5 列表元组字典

数据可视化 matplotlib词云图Pyecharts

海龟画图PandasBug处理电脑小知识

自动化脚本编程工具NumPy CSVWeb

Pygame  图像处理    机器学习数据库

最新文章

随机文章