首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python:将SwigPythonObject转换为Python对象

Python:将SwigPythonObject转换为Python对象
EN

Stack Overflow用户
提问于 2016-09-06 08:22:12
回答 1查看 1.9K关注 0票数 1

我正在使用一些封闭的Python模块:我可以通过API调用方法,但无法访问实现。我知道这个模块基本上是包装了一些C++代码。

因此,返回值类型之一是SwigPythonObject。以后如何处理这个对象,假设我没有来自模块分发服务器或文档的任何其他辅助工具?

我希望以某种方式将他转换为“常规”python对象,并在调试器中观察他的内部成员结构。

目前,我在调试器中看到的情况如下:

代码语言:javascript
复制
{SwigPythonObject} _<hexa number>_p_unsigned_char
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-06 20:47:08

您所要求的内容的语义有点不清楚,但从根本上看,您似乎得到了一个指向unsigned char的指针,来自您想要使用的SWIG。稍微猜一下,大概有3种情况下你可能会遇到这样的情况:

  1. 指针实际上是指向单个无符号字节的指针。
  2. 指针是指向以空结尾的字符串的指针.(为什么它不只是包装成一个字符串呢?)
  3. 指针指向一个固定长度的无符号字节数组。(你需要知道/猜出长度)

在这个特殊的例子中,由于对所有三种情况都没有需要考虑的打包或对齐问题,我们实际上可以为上述所有情况编写一些东西,使用ctype来读取直接引用到Python中的内存,并附带执行SWIG代理。(请注意,如果我们所查看的类型比指向它们的单个内置类型或数组的指针更复杂,那么我们就无法在这里做很多事情)

首先,在C- test.h中使用一些代码来练习我们正在做的工作:

代码语言:javascript
复制
inline unsigned char *test_str() {
  static unsigned char data[] = "HELLO WORLD";
  return data;
}

inline unsigned char *test_byte() {
  static unsigned char val = 66;
  return &val;
}

接下来是一个最小的SWIG模块,它封装如下:

代码语言:javascript
复制
%module test

%{
#include "test.h"
%}

%include "test.h"

我们可以在ipython中检查这一点,并看到它被包装(类似于您所观察到的):

代码语言:javascript
复制
In [1]: import test

In [2]: test.test_byte()
Out[2]: <Swig Object of type 'unsigned char *' at 0x7fc2851cbde0>

In [3]: test.test_str()
Out[3]: <Swig Object of type 'unsigned char *' at 0x7fc2851cbe70>

In [4]: hex(int(test.test_str()))
Out[4]: '0x7f905b0e72cd'

我们在每一种情况下使用的是这样一个事实:调用int(x),其中x是未知的SWIG,无符号字符指针,给出指针作为整数指向的地址的值。结合ctype的from_address静态方法,我们可以构造ctype实例来直接访问内存SWIG所知道的内容。(注意:调用int()返回的地址与字符串表示中显示的地址不匹配,因为前者是指向的数据的真实地址,而后者是SWIG代理对象的地址)

最简单的包装方式可能是固定长度的情况--我们可以在适当大小的*上使用c_ubyte操作符创建一个ctype类型,然后调用from_address

对于以空结尾的字符串情况,我们实际上有两个选择:要么使用libc strlen函数计算字符串长度,然后构造匹配的ctype类型,要么使用Python中的char循环char,直到我们达到null为止。我在下面的例子中选择了后者,因为它更简单。不过,通过使用生成器和itertools.count()来跟踪位置,我可能过于复杂了。

最后,对于指向单字节情况的指针,我基本上重用了现有的ctype类型,我必须创建一个1字节数组并从中读取值。可能有一种方法可以使用ctypes.POINTER(ctypes.c_ubyte).contents从一个地址构造一个类型,但是我无法很快看到它,所以使用1字节数组技巧使它对我来说微不足道。

所有这些都为我提供了以下Python代码:

代码语言:javascript
复制
import ctypes
import test
import itertools

# Case 2
def swig_to_str(s):
  base = int(s)
  ty = ctypes.c_ubyte*1
  def impl():
    for x in itertools.count():
      v=ty.from_address(base+x)[0]
      if not v: return
      yield chr(v)
  return ''.join(impl())

# Case 1
def swig_to_byte(b):
  ty=ctypes.c_ubyte*1
  v=ty.from_address(int(b))
  return v[0]

# Case 3
def swig_to_fixed_len(s, l):
  ty=ctypes.c_ubyte*l
  return ''.join(chr(x) for x in ty.from_address(int(s)))

t=test.test_str()
print(t)
print(swig_to_str(t))
print(swig_to_fixed_len(t,5))

u=test.test_byte()
print(u)
print(swig_to_byte(u))

这与Python2.7如出一辙(只需最少的努力就可以将其修改为3):

代码语言:javascript
复制
swig3.0 -python -Wall test.i
gcc -std=gnu99 -Wall test_wrap.c -o  _test.so -shared -I/usr/include/python2.7/ -fPIC
python run.py 

<Swig Object of type 'unsigned char *' at 0x7f4a57581cf0>
HELLO WORLD
HELLO
<Swig Object of type 'unsigned char *' at 0x7f4a57581de0>
66
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39344039

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档