利用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中args的含义

    Python中args的含义在Python的函数定义中,如果我们想要传入不定数量的参数,可以使用args。在这篇文章中,我们将详细介绍Python中args的含义以及如何使用它来实现不定数量参数的传递。

    2024-05-27
    58
  • SQL Mode_odbc driver 17 for sql server

    SQL Mode_odbc driver 17 for sql server
    mysql 可以运行在不同的 SQL Mode模式下,不同的SQL Mode定义了不同的SQL语法,有不同的数据校验规则。 SQL Mode的作用: 不同的…

    2023-04-09
    177
  • 商业银行营销战略的4P策略是指_银行如果加强营销协同

    商业银行营销战略的4P策略是指_银行如果加强营销协同     作为银行其发展信息技术的基础是确保信息系统的安全。而应用交付厂商F5的应用交付解解决方案在应用安全领域的技术优势可以为银行发展做好保驾护航的任务。光这么说可能有些空洞,下面我们以秦皇岛银行…

    2023-02-11
    144
  • 【赵强老师】搭建Hadoop环境[通俗易懂]

    【赵强老师】搭建Hadoop环境[通俗易懂]说明:这里我们以本地模式和伪分布模式伪列,为大家介绍如何搭建Hadoop环境。有了这个基础,大家可以自行搭建Hadoop的全分布模式。 需要使用的安装介质: hadoop-2.7.3.tar.gz j

    2023-02-13
    155
  • 荣耀笔记本如何升级win11_荣耀win10系统版本

    荣耀笔记本如何升级win11_荣耀win10系统版本     荣耀MagicBook科技尝鲜版发布已经有一段时间了,这个预装了Linux版本的笔记本在原来已经极具性价比的基础上又便宜了300元,而荣耀笔记本如何安装Win10系统俨然成为了热门话题。对…

    2022-12-19
    170
  • 制造行业的数据管理「建议收藏」

    制造行业的数据管理「建议收藏」制造行业的IT应用ERP/CRMOA/邮件系统制造业数据管理需求汇总数据分层管理数据库实时复制终端数据管理集中备份备份到云连续数据复制到云在云中恢复云中备份、多数据中心今天先到这儿,希望对技术领导力,

    2023-01-24
    145
  • 使用PyCharm进行Python编程的教程

    使用PyCharm进行Python编程的教程Python是一种高级编程语言,可以用于各种任务,从Web开发到科学计算和数据分析等。而PyCharm是一款功能强大的Python IDE,提供了许多工具和插件,帮助Python开发人员更好地编写和调试Python程序。

    2024-05-29
    47
  • Python 实用技能大杂烩

    Python 实用技能大杂烩日期处理对于开发工程师来说非常重要,而在Python中,datetime模块是我们的好帮手。当我们拿到一个时间戳后,想要将其转换成可读时间格式,可以按照下面的代码示例进行:

    2024-03-02
    75

发表回复

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