将 FILE * 从 Python / ctypes 传递到函数中

2024-03-06

我有一个库函数(用 C 编写),它通过将输出写入到来生成文本FILE *。我想用 Python (2.7.x) 包装它,并使用创建临时文件或管道的代码,将其传递到函数中,从文件中读取结果,并将其作为 Python 字符串返回。

这是一个简化的示例来说明我所追求的内容:

/* Library function */
void write_numbers(FILE * f, int arg1, int arg2)
{
   fprintf(f, "%d %d\n", arg1, arg2);
}

Python 包装器:

from ctypes import *
mylib = CDLL('mylib.so')


def write_numbers( a, b ):
   rd, wr = os.pipe()

   write_fp = MAGIC_HERE(wr)
   mylib.write_numbers(write_fp, a, b)
   os.close(wr)

   read_file = os.fdopen(rd)
   res = read_file.read()
   read_file.close()

   return res

#Should result in '1 2\n' being printed.
print write_numbers(1,2)

我想知道我最好的选择是什么MAGIC_HERE().

我很想用ctypes并创建一个libc.fdopen()返回 Python c_void_t 的包装器,然后将其传递到库函数中。我觉得这在理论上应该是安全的——只是想知道这种方法或解决这个问题的现有 Python 主义是否存在问题。

此外,这将是一个长期运行的过程(假设“永远”),因此任何泄漏的文件描述符都会出现问题。


First, do note that FILE* is an stdio-specific entity. It doesn't exist at system level. The things that exist at system level are descriptors (retrieved with file.fileno() https://docs.python.org/2/library/stdtypes.html?highlight=fileno#file.fileno) in UNIX (os.pipe() returns plain descriptors already) and handles (retrieved with msvcrt.get_osfhandle() https://docs.python.org/2/library/msvcrt.html?highlight=msvcrt#msvcrt.get_osfhandle) in Windows. Thus it's a poor choice as an inter-library exchange format if there can be more than one C runtime in action. You'll be in trouble if your library is compiled against another C runtime than your copy of Python: 1) binary layouts of the structure may differ (e.g. due to alignment or additional members for debugging purposes or even different type sizes); 2) in Windows, file descriptors that the structure links to are C-specific entities as well, and their table is maintained by a C runtime internally1 https://stackoverflow.com/questions/33310675/pass-file-into-function-from-python-ctypes/33311066#comment54499370_33311066.

此外,在 Python 3 中,对 I/O 进行了彻底修改,以便将其从stdio. So, FILE*与 Python 风格格格不入(很可能,大多数非 C 风格也是如此)。

现在,你需要的是

  • 以某种方式猜测您需要哪个 C 运行时,并且
  • 称其为fdopen() http://linux.die.net/man/3/fdopen(或同等学历)。

(Python 的座右铭之一is毕竟,“让正确的事情变得容易,让错误的事情变得困难”)


最干净的方法是使用库链接到的精确实例(请祈祷它是动态链接的,否则将没有导出的符号可供调用)

对于第一项,我找不到任何可以分析加载的动态模块元数据以找出它已链接的 DLL/so 的 Python 模块(仅名称甚至名称+版本是不够的,你知道,由于系统上可能存在该库的多个实例)。尽管这绝对是可能的,因为有关其格式的信息是广泛可用的。

对于第二项,这是一个微不足道的事情ctypes.cdll('path').fdopen (_fdopen对于 MSVCRT)。


其次,您可以创建一个小型帮助程序模块,该模块将针对与库相同(或保证兼容)的运行时进行编译,并为您从上述描述符/句柄进行转换。这实际上是编辑库的有效解决方法。


最后,有一个最简单(也是最脏)的方法,通过 Python C API 使用 Python 的 C 运行时实例(因此上述所有警告都完全适用)ctypes.pythonapi https://docs.python.org/2/library/ctypes.html?highlight=pythonapi。它利用了

  • Python 2 的类文件对象是包装器这一事实stdio's FILE*(Python 3 则不然)
  • PyFile_AsFile https://docs.python.org/2/c-api/file.html?highlight=pyfile_asfile#c.PyFile_AsFile API that returns the wrapped FILE* (note that it's missing from Python 3 https://docs.python.org/3/c-api/file.html?highlight=pyfile_asfile#c.PyFile_AsFile)
    • 对于独立的fd,你需要首先构造一个类似文件的对象(这样就会有一个FILE*回来 ;) )
  • the fact that id() https://docs.python.org/2/library/functions.html?highlight=id#id of an object is its memory address (CPython-specific)2 https://stackoverflow.com/questions/33310675/pass-file-into-function-from-python-ctypes/33311066#comment54426705_33311066

    >>> open("test.txt")
    <open file 'test.txt', mode 'r' at 0x017F8F40>
    >>> f=_
    >>> f.fileno()
    3
    >>> ctypes.pythonapi
    <PyDLL 'python dll', handle 1e000000 at 12808b0>
    >>> api=_
    >>> api.PyFile_AsFile
    <_FuncPtr object at 0x018557B0>
    >>> api.PyFile_AsFile.restype=ctypes.c_void_p   #as per ctypes docs,
                                             # pythonapi assumes all fns
                                             # to return int by default
    >>> api.PyFile_AsFile.argtypes=(ctypes.c_void_p,) # as of 2.7.10, long integers are
                    #silently truncated to ints, see http://bugs.python.org/issue24747
    >>> api.PyFile_AsFile(id(f))
    2019259400
    

请记住fds 和 C 指针,您需要手动确保正确的对象生命周期!

  • file-like objects returned by os.fdopen() do close the descriptor on .close()
    • 所以重复描述符os.dup()如果您在文件对象关闭/垃圾收集后需要它们
  • 在使用 C 结构时,调整相应对象的引用计数PyFile_IncUseCount() https://docs.python.org/2/c-api/file.html?highlight=pyfile_asfile#c.PyFile_IncUseCount/PyFile_DecUseCount() https://docs.python.org/2/c-api/file.html?highlight=pyfile_asfile#c.PyFile_DecUseCount.
  • 确保描述符/文件对象上没有其他 I/O,因为它会搞砸数据(例如,自从调用iter(f)/for l in f,内部缓存是独立于stdio的缓存)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 FILE * 从 Python / ctypes 传递到函数中 的相关文章

  • Spark 和 Python 使用自定义文件格式/生成器作为 RDD 的输入

    我想问一下 Spark 中输入的可能性 我可以看到从http spark apache org docs latest programming guide html http spark apache org docs latest pro
  • 两个不同长度的数据帧的列之间的余弦相似度?

    我在 df1 中有文本列 在 df2 中有文本列 df2 的长度将与 df1 的长度不同 我想计算 df1 text 中每个条目与 df2 text 中每个条目的余弦相似度 并为每场比赛给出分数 输入样本 df1 mahesh suresh
  • pandas 相当于 np.where

    np where具有向量化 if else 的语义 类似于 Apache Spark 的when otherwise数据帧方法 我知道我可以使用np where on pandas Series but pandas通常定义自己的 API
  • 如何查找或安装适用于 Python 的主题 tkinter ttk

    过去 3 个月我一直在制作一个机器人 仅用代码就可以完美运行 现在我的下一个目标是为它制作一个 GUI 但是我发现了一些障碍 主要的一个是能够看起来不像一个 30 年前的程序 我使用的是 Windows 7 我仅使用 Python 3 3
  • Airflow 1.9 - 无法将日志写入 s3

    我在 aws 的 kubernetes 中运行气流 1 9 我希望将日志发送到 s3 因为气流容器本身的寿命并不长 我已经阅读了描述该过程的各种线程和文档 但我仍然无法让它工作 首先是一个测试 向我证明 s3 配置和权限是有效的 这是在我们
  • 在骨架图像中查找线 OpenCV python

    我有以下图片 我想找到一些线来进行一些计算 平均长度等 我尝试使用HoughLinesP 但它找不到线 我能怎么做 这是我的代码 sk skeleton mask rows cols sk shape imgOut np zeros row
  • 在Raspberry pi上升级skimage版本

    我已经使用 Raspberry Pi 2 上的 synaptic 包管理器安装了 python 包 然而 skimage 模块版本 0 6 是 synaptic 中最新的可用版本 有人可以指导我如何将其升级到0 11 因为旧版本中缺少某些功
  • 在 azure blob 存储中就地创建 zip 文件

    我将文件存储在 Blob 存储帐户内的一个容器中 我需要在第二个容器中创建一个 zip 文件 其中包含第一个容器中的文件 我有一个使用辅助角色和 DotNetZip 工作的解决方案 但由于 zip 文件的大小最终可能达到 1GB 我担心在进
  • Unity c# 四元数:将 y 轴与 z 轴交换

    我需要旋转一个对象以相对于现实世界进行精确旋转 因此调用Input gyro attitude返回表示设备位置的四元数 另一方面 这迫使我根据这个四元数作为默认旋转来计算每个旋转 将某些对象设置为朝上的简单方法如下 Vector3 up I
  • 可以使用哪些技术来衡量 pandas/numpy 解决方案的性能

    Question 如何简洁全面地衡量下面各个功能的性能 Example 考虑数据框df df pd DataFrame Group list QLCKPXNLNTIXAWYMWACA Value 29 52 71 51 45 76 68 6
  • 如何在多线程应用程序中安全地填充数据并 Refresh() DataGridView?

    我的应用程序有一个 DataGridView 对象和一个 MousePos 类型的列表 MousePos 是一个自定义类 它保存鼠标 X Y 坐标 类型为 Point 和该位置的运行计数 我有一个线程 System Timers Timer
  • MySQL 连接器 C++ 64 位在 Visual Studio 2012 中从源代码构建

    我正在尝试建立mySQL 连接器 C 从源头在视觉工作室2012为了64 bit建筑学 我知道这取决于一些boost头文件和C 连接器 跑步CMake生成一个项目文件 但该项目文件无法编译 因为有一大堆非常令人困惑的错误 这些错误可能与包含
  • 如何在亚马逊 EC2 上调试 python 网站?

    我是网络开发新手 这可能是一个愚蠢的问题 但我找不到可以帮助我的确切答案或教程 我工作的公司的网站 用 python django 构建 托管在亚马逊 EC2 上 我想知道从哪里开始调试这个生产站点并检查存储在那里的日志和数据库 我有帐户信
  • AWS Lambda 不读取环境变量

    我正在编写一个 python 脚本来查询 Qualys API 中的漏洞元数据 我在 AWS 中将其作为 lambda 函数执行 我已经在控制台中设置了环境变量 但是当我执行函数时 出现以下错误 module initialization
  • 如何给URL添加变量?

    我正在尝试从网站收集数据 我有一个 Excel 文件 其中包含该网站的所有不同扩展名 F i www example com example2 我有一个脚本可以成功从网站中提取 HTML 但现在我想为所有扩展自动执行此操作 然而 当我说 s
  • 构建 C# MVC 5 站点时项目之间的处理器架构不匹配

    我收到的错误如下 2017 年 4 月 20 日构建 13 23 38 C Windows Microsoft NET Framework v4 0 30319 Microsoft Common targets 1605 5 警告 MSB3
  • 如何获取带有某个属性注释的所有属性?

    我刚刚从 Roslyn 开始 我想找到所有用属性名称 OneToOne 注释的属性 我启动了 SyntaxVisualizer 并能够获取对该节点的引用 但我想知道是否有更简单的方法来实现此目的 这就是我所拥有的 var prop docu
  • .Net Reactive Extensions Framework (Rx) 是否考虑拓扑顺序?

    Net 反应式扩展框架是否按拓扑顺序传播通知以最大限度地减少更新量 就像 Scala Rx 所做的那样 Net 反应式扩展 Rx 是否可以 https github com lihaoyi scala rx wiki How it Work
  • 定义在文本小部件中双击时选择哪些字符

    在 Windows 上 双击文本小部件中的单词也将选择连接的标点符号 有什么方法可以定义您想要选择的角色吗 tcl wordchars该变量的值是一个正则表达式 可以设置它来控制什么被视为 单词 字符 例如 通过双击 Tk 中的文本来选择单
  • 嵌入式linux编写AT命令

    我在向 GSM 模块写入 AT 命令时遇到问题 当我使用 minicom b 115200 D dev ttySP0 term vt100 时它工作完美 但我不知道如何在 C 代码中做同样的事情 我没有收到任何错误 但模块对命令没有反应 有

随机推荐

  • Cocoa 与 MacOS X 钥匙串的接口

    我有一些 Mac 代码需要存储 访问和更新密码 以便将用户与 Web API 连接起来 放置这些信息的正确位置应该是 Mac Keychain 但似乎没有 cocoa 界面 请参阅这个答案 https stackoverflow com a
  • 在 Devise on Rails 中使用单独的身份验证模型

    我有一个简单的解决方案 我用以下对象自己制作 Account 具有 token 字段 在身份验证时返回并在 API 调用中使用 验证 具有 auth type auth id 和对帐户的引用 我有一个单独的验证模型能够连接多种登录方式 设备
  • Android SimpleDateFormat格式问题

    我正在尝试将日期格式化为所需的格式 但我收到的日期错误 这就是我正在做的事情 我收到的日期如下 3 24 2012 8 25 03 AM 3 23 2012 2 57 01 PM 3 15 2012 9 28 01 AM 并想将它们展示为
  • 为什么 KeyPairGenerator.genKeyPair() 这么慢

    我有一些 Java 代码 当我运行函数时KeyPairGenerator genKayPair 工作时间为 40 秒或更长时间 如何改变这种现状呢 如果我跑 openssl req x509 nodes days 365 newkey rs
  • 如何选择.NET版本来编译项目?

    我有VS2005 如何在特定版本的 NET 下编译我的项目 我已经安装了 1 0 2 0 3 0 和 3 5 提前Tnx 恐怕你不能 VS2005仅适用于 NET框架2 0 您需要适当版本的 Visual Studio 才能与其他版本一起使
  • Angular 4文档离线计算机[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想找到 Angular 4 文档的本地 离线版本 https angular io docs htt
  • 如何在 RxJava 中计算移动平均线

    在金融领域 我们通常需要从时间序列数据流中计算移动窗口总值 以移动平均线为例 假设我们有以下数据流 T是时间戳 V是实际值 T0 V0 T1 V1 T2 V2 T3 V3 T4 V4 T5 V5 T6 V6 T7 V7 T8 V8 T9 V
  • 如何将字符串转换为 NSDate?

    我有每当有新的远程通知时收到的字符串 我正在为我的后端使用解析 我检索到的字符串来自 createdAt 列 我试过下面的代码 var ca 2015 07 03T03 16 17 220Z var dateFormater NSDateF
  • 使用带淘汰赛的引导按钮下拉菜单

    我正在尝试使用 Bootstrap 的精美样式按钮下拉菜单 http getbootstrap com components btn dropdowns淘汰赛 不幸的是 下拉菜单是使用链接而不是
  • LISP - 小数点后的数字

    有谁知道如何在 Lisp 中指定浮点数小数点后的位数 假设我在 REPL 上打印此命令 CL USER 3 gt format t 15f float 1 7 I get 0 142857150000000 但是该数字四舍五入到小数点后第
  • 使用 7zip 检测文件是否为存档

    我想使用 SevenZipSharp 来确定文件是否是存档 我知道这是可能的 因为在资源管理器中 如果我将 zip 重命名为 bmp 7zip 仍然会将其识别为存档 edit 换句话说 我希望 7zip 告诉我文件 无论扩展名如何 是否包含
  • ASP.NET 网站的自定义登录机制

    我正在开发一个 ASP NET 网站 我需要摆脱一些自定义但简单的登录机制 我从著名的员工信息入门套件 http eisk codeplex com 这是我到目前为止所拥有的 在 ASP NET 页面上 protected void But
  • Facebook Graph Api 2.1 从用户名获取用户 ID

    我正在寻找一个可以从个人资料网址或 Facebook 用户名中提供用户 ID 的解决方案 example http facebook com username 获取此 url 的用户 ID 而且当我尝试读取朋友 我有朋友相关权限 时 我得到
  • Parse.com 关系查询问题

    我有以下表格名称 aniStudii 和 discipline 我也制作了屏幕截图 正如您所看到的 这些表之间在 mateii 列中存在关系 aniStudii 中 Anul I 列的行具有一个值 另一列具有不同的值 这些值可以在 disc
  • JavaScript 乘以 100 给出奇怪的结果[重复]

    这个问题在这里已经有答案了 I have var a 0 0532 var b a 100 b 应该返回 5 32 但它返回 5 319999999999999 我该如何解决 JSFiddle 在这里 http jsfiddle net 9
  • fseek() 函数中的零偏移量与 SEEK_CUR 有什么用?

    while fread product sizeof Product 1 file 1 product price 2 0 fseek file sizeof Product SEEK CUR fwrite product sizeof P
  • 从 package.json 脚本中调用带有参数的 javascript 函数

    javascript 文件 foo js 具有以下内容 function foo param console log foo called with params console log param module exports foo f
  • 编辑后保留PDB文件格式。

    我有 xxx pdb 文件 ATOM 1910 CB SER 128 45 806 50 621 39 840 1 00 9 36 ATOM 1913 OG SER 128 44 538 51 195 39 571 1 00 9 36 AT
  • Given import java util public class Hancock insert code here list add foo 哪两个代码片段独立插入到第 5 行 编译时不会出现警告 选择两项 A public void
  • 将 FILE * 从 Python / ctypes 传递到函数中

    我有一个库函数 用 C 编写 它通过将输出写入到来生成文本FILE 我想用 Python 2 7 x 包装它 并使用创建临时文件或管道的代码 将其传递到函数中 从文件中读取结果 并将其作为 Python 字符串返回 这是一个简化的示例来说明