【问题标题】:Create a buffer and assign it a pointer in Python在 Python 中创建一个缓冲区并为其分配一个指针
【发布时间】:2014-11-17 22:26:49
【问题描述】:

我有一个用 Python 编写的小应用程序。它需要接受用户输入(来自 cmd 行):

def wr(input=0):   
    p = struct_t() # a C struct
    p.data = input # p.data is a pointer
    c_function(p)

这里的数据最多可以是 32 个单词。 struct struct_tdata 字段的类型为 uint32_t *

上面的代码给了我一个p.data = input 类型不匹配的错误。我想要的是在 Python 中有一个缓冲区,它接受用户输入并让指针 p.data 指向该缓冲区,以便我可以将 p 传递给我的 C 例程。

我知道我可以创建一个字符串缓冲区,并以非常直接的方式使用 ctypes 将其转换为类型 uint32_t *,但我想知道在 SWIG 中是否有办法做到这一点。非常感谢。

【问题讨论】:

  • 您希望input 的类型是什么?如果它是一个整数列表,这很容易。
  • @Flexo 我认为只是整数,比如 input=479825793457392574390954370…(很长,最多 32 个字)谢谢。
  • 那永远不适合 32 位整数。
  • @rowan.G 是的,感谢您指出。那么我想它应该是一个整数列表。谢谢。

标签: python c swig


【解决方案1】:

要使用 SWIG 将 Python 脚本与 C 项目连接起来,第一步是创建一个接口文件,其中包含将由 Python 调用的 C 函数(即接口函数),例如 buffer.i 如下。

/* File: buffer.i */
%module buffer

%{
#define SWIG_FILE_WITH_INIT
#include "buffer.h"
%}

void wr(int idx, unsigned int val);
unsigned int rd(int idx);

保持界面简单,将复杂性留给在后台运行的 C 是一个很好的做法。相应地,您可以手动创建一个C头文件(buffer.h)和实现文件(buffer.c),如下所示。

这里是 buffer.h

/* File: buffer.h */

#include <stdint.h>

void wr(int idx, unsigned int val);
unsigned int rd(int idx);

这里是 buffer.c

/* File: buffer.c */

#include "buffer.h"

#define BUF_SIZE 32

unsigned int buf[BUF_SIZE];

void wr(int idx, unsigned int val) {
  buf[idx%BUF_SIZE] = val;
}

unsigned int rd(int idx) {
  return buf[idx%BUF_SIZE];
}

你需要一个安装文件(setup.py):

#!/usr/bin/env python

"""
setup.py file for SWIG buffer
"""

from distutils.core import setup, Extension


buffer_module = Extension('_buffer',
                           sources=['buffer_wrap.c', 'buffer.c'],
                           )

setup (name = 'buffer',
       version = '0.1',
       author      = "SWIG Docs",
       description = """Simple swig buffer from docs""",
       ext_modules = [buffer_module],
       py_modules = ["buffer"],
       )

现在您可以使用 SWIG 通过发出以下命令来构建项目:

$ swig -python buffer.i
$ python setup.py build_ext --inplace

上面的命令会自动生成buffer.py,它给你调用者框架(在Python端)。打开这个文件,你会看到_buffer.wr_buffer.rd 已经被创建了。为了一次转换一个非常长的 int(Python 风格)32 位并将其保存在 C 数组中,您可以在 buffer.py 中添加一个包装函数,该函数调用自动生成的 Python 函数wr多次:

def wr1(args):
  for n in range(0, 32):
    val = args & 0xffffffff
    wr(n, val)
    args >>= 32
    if args == 0:
      break

现在您可以运行 Python。这是您在运行时看到的内容:

>>> import buffer
>>> buffer.wr1(0x12345678deadbeef)
>>> hex(buffer.rd(0))
'0xdeadbeef'
>>> hex(buffer.rd(1))
'0x12345678'

【讨论】:

  • 感谢您的回答。但是你能解释一下 _buffer.wr 和 _buffer.rd 是什么吗?我还是不知道c函数是怎么和Python联系起来的。我不需要为 SWIG 修改 .i 文件?
  • @JFreebird:提供更多细节更新。
  • 顺便说一句,这里是描述使用 SWIG for Python 的链接:swig.org/Doc1.3/Python.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 2013-09-13
  • 1970-01-01
  • 2012-09-29
  • 2022-12-06
相关资源
最近更新 更多