利用Python CFFI进行原子级别的C库调用

利用Python CFFI进行原子级别的C库调用Python是一种高级语言,常用于快速开发、数据挖掘等领域,但有时候需要借助C库进行密集计算等操作。Python提供了很多种方式进行C库调用,例如ctypes、Swig等,但各种方式都存在一些问题。CFFI是Python官方推荐的C库调用方式,提供了原子级别的C库调用能力,一致性强,灵活性高,效率较高,已被广泛应用于NumPy、PyPy、Pillow等多个Python库。

介绍

Python是一种高级语言,常用于快速开发、数据挖掘等领域,但有时候需要借助C库进行密集计算等操作。Python提供了很多种方式进行C库调用,例如ctypes、Swig等,但各种方式都存在一些问题。CFFI是Python官方推荐的C库调用方式,提供了原子级别的C库调用能力,一致性强,灵活性高,效率较高,已被广泛应用于NumPy、PyPy、Pillow等多个Python库。

正文

一、CFFI的基础使用

使用CFFI调用C库的过程包括三步:

  1. 定义C函数接口
  2. from cffi import FFI ffi = FFI() lib = ffi.dlopen('libc.so.6') # 定义C函数接口 # void 则表示没有返回值 # int 则表示返回值类型是整数 # int, int 表示C函数接收两个整数类型的参数 add = lib.printf add.argtypes = ffi.typeof("char *") add.restype = ffi.typeof("int")
  3. 调用C函数接口
  4. # 调用C函数接口 result = add(b"Hello World") print(result)
  5. 编译代码
  6. gcc -shared -o libtest.so test.c

二、CFFI与ctypes的比较

ctypes是Python内置的C库调用方式,也是使用比较广泛的一种方式,但与CFFI相比还是存在一些差异:

  • 使用方式:CFFI要求对C语言的代码重构最小,而ctypes则要求用户按照ctypes的规范来组织C代码。
  • 兼容性:CFFI兼容性良好,支持多个平台,而ctypes不一定能够在所有平台上正常使用。
  • Python版本:CFFI仅支持Python2.6、Python2.7、Python3.2以及更高版本,而ctypes作为Python内置库则兼容Python2.6 ~ Python3.x各版本。

三、CFFI的高级使用

除了基本的C库调用之外,CFFI还提供了一些高级功能,例如:

  • Struct类型的支持
  • from cffi import FFI ffi = FFI() cpp_code = ''' #include #include struct PointF { float x; float y; }; typedef struct PointF PointF; void show_point(PointF p) { printf("%0.1f, %0.1f", p.x, p.y); }''' # 声明C数据结构 ffi.cdef(""" typedef struct { float x; float y; } PointF; void show_point(PointF); """) lib = ffi.verify(cpp_code, libraries=[]) p = ffi.new('PointF*', [1.5, 2.4]) lib.show_point(p[0])
  • Union类型的支持
  • from cffi import FFI ffi = FFI() cpp_code = ''' #include union Shape { int shape_type; struct { int x; int y; int width; int height; } rect; }; typedef union Shape Shape; void show_rect(Shape r) { printf("(%d, %d, %d, %d)", r.rect.x, r.rect.y, r.rect.width, r.rect.height); }''' ffi.cdef(""" typedef union { int shape_type; struct { int x; int y; int width; int height; } rect; } Shape; void show_rect(Shape); """) lib = ffi.verify(cpp_code, libraries=[]) s = ffi.new('Shape*', [0]) s.rect.x = 1 s.rect.y = 2 s.rect.width = 3 s.rect.height = 4 lib.show_rect(s[0])

代码部分

以下是一个使用CFFI调用Windows API的例子:

# -*- coding: utf-8 -*- from cffi import FFI # 定义C函数接口 ffi = FFI() ffi.cdef(""" typedef struct _FILETIME { unsigned long dwLowDateTime; unsigned long dwHighDateTime; } FILETIME, *PFILETIME, *LPFILETIME; typedef struct _SYSTEMTIME { short wYear; short wMonth; short wDayOfWeek; short wDay; short wHour; short wMinute; short wSecond; short wMilliseconds; } SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; void GetSystemTime(SYSTEMTIME *lpSystemTime); void SystemTimeToFileTime(const SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime); void FileTimeToLocalFileTime(CONST FILETIME *lpFileTime, LPFILETIME lpLocalFileTime); BOOL FileTimeToSystemTime(const FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime); """) lib = ffi.dlopen('kernel32.dll') # 调用GetSystemTime函数,获取当前系统时间(UTC) system_time = ffi.new('SYSTEMTIME *') lib.GetSystemTime(system_time) # 将UTC时间转换为本地时间 file_time_utc = ffi.new('FILETIME *') lib.SystemTimeToFileTime(system_time, file_time_utc) file_time_local = ffi.new('FILETIME *') lib.FileTimeToLocalFileTime(file_time_utc, file_time_local) # 获取系统时间(本地时间) local_time = ffi.new('SYSTEMTIME *') lib.FileTimeToSystemTime(file_time_local, local_time) print('Local Time:', local_time.wYear, local_time.wMonth, local_time.wDay, local_time.wHour, local_time.wMinute, local_time.wSecond, local_time.wMilliseconds)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/20370.html

(0)
上一篇 2024-06-30
下一篇 2024-06-30

相关推荐

  • 用Python编写自定义界面的库

    用Python编写自定义界面的库Python是一个优秀的编程语言,它的优点是简洁、易读、易学、功能强大。Python语言可以用于Web开发、数据科学、人工智能等众多领域。在本文中,我们将介绍如何使用Python编写自定义界面的库。

    2024-04-02
    68
  • 使用Python编写文件操作程序

    使用Python编写文件操作程序在Python中进行文件读取操作非常简单,只需要使用open函数打开文件,指定读取模式即可。

    2024-02-29
    79
  • 什么是idle

    什么是idlePython是一种高级编程语言,其优雅的语法和强大的扩展性让它成为众多开发人员的选择。然而,相对于其他编程语言,Python的开发工具比较简单,有些开发者甚至选择在文本编辑器中手动编写Python代码。在这种情况下,IDLE就成为了一个非常有用的工具。

    2024-05-18
    56
  • postgresql计算两个时间相差天数[通俗易懂]

    postgresql计算两个时间相差天数[通俗易懂]1.date_part,可以算出相差的天数,结果向下取整,括号里面的参数可以改成year、month、hour、minutes等,值得注意的是,改成对应的参数,是用相应的时间减去时间,例如用hour…

    2022-12-27
    182
  • 如何在vim中退出编辑模式

    如何在vim中退出编辑模式在vim编辑器中,最常用的方法是通过按Esc键退出编辑模式。当处于插入模式时,按下Esc键即可退出。这种方法最简单,最常用,有利于加速编辑器的操作。

    2024-04-14
    76
  • Python字典遍历方法及示例

    Python字典遍历方法及示例Python字典是一种无序的key-value集合,其中每个元素由key和value组成。在很多场合下,需要遍历字典来获取字典中的数据。Python字典提供了多种遍历方法,可以满足不同需求。

    2024-05-12
    73
  • 本溪哪里可以开医院门诊发票-中国新闻网[亲测有效]

    本溪哪里可以开医院门诊发票-中国新闻网[亲测有效]本溪哪里可以开医院门诊发票【152 * 9б 28 * 21 б9】陈生,诚、信、合、作,保、真、售、后、保、障、长、期、有、效。adb的全称为Android Debug Bridge,是Andro…

    2023-01-31
    151
  • 查询字段中含有汉字的sql

    查询字段中含有汉字的sql1.利用ASCIISTR这个函数查询,查询字段为bid_amount select * from project_win_info where ASCIISTR(bid_amount) like ‘…

    2023-04-01
    149

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注