tl;dr Python 的 ctypes
文档中描述的 _as_parameter_
和 from_param
机制似乎并不适用在 OS X 中工作正常。我们的代码或 ctypes
有问题吗?
一些背景
GenomeTools library包括广泛的 C API 以及一小部分使用 ctypes
实现的 Python 绑定(bind)。我经常使用 C API,但我对使用和贡献该项目的 Python 代码很感兴趣。 C 代码位于 src/
中,Python 绑定(bind)在 gtpython/
中实现。
我编写了一个虚拟脚本来测试。
from gt import *
print "DEBUG a"
ingff3 = GFF3InStream("testdata/Scaffold_102.gff3")
print "DEBUG b"
outgff3 = GFF3OutStream(ingff3)
print "DEBUG c"
outgff3.pull()
print "DEBUG d"
问题
忽略特定于库的详细信息,GFF3InStream
和 GFF3OutStream
类是 C 对象类型的 Python 包装器。 GFF3OutStream
构造函数调用 C 库中的构造函数 gt_gff3_out_stream_new
。该 C 函数的第一个参数应该是指向 C 对象的指针。调用该函数的Python代码提供了一个Python对象作为参数,但由于该对象设置了_as_parameter_
属性并定义了from_param
方法,因此将值传递给C code实际上是Python对象封装的指针,而不是指向Python对象本身的指针。
至少是这个想法,这就是它在 Linux 上的工作原理。但在 Mac OS X 上,我遇到了各种段错误,因为这些机制似乎不起作用。仅当我显式更改构造函数时...
class GFF3OutStream(GenomeStream):
def __init__(self, genome_stream):
self.gs = gtlib.gt_gff3_out_stream_new(genome_stream, None)
self._as_parameter_ = self.gs
...对此...
class GFF3OutStream(GenomeStream):
def __init__(self, genome_stream):
self.gs = gtlib.gt_gff3_out_stream_new(genome_stream.gs, None)
self._as_parameter_ = self.gs
...我是否观察到我的小虚拟脚本在 OS X 上的正确行为。
_as_parameter_
和 from_param
机制在 Mac OS X 上真的不可用吗?这是 Python 的 ctypes 的已知问题吗?或者 GenomeTools 代码有问题吗?
最佳答案
getfunc
的c_void_p
以整数形式返回指针值。整数参数的默认转换是 C int
,它截断 64 位指针值。
至少有两种方法可以解决这个问题。将整数结果包装在 c_void_p
中.
class GFF3OutStream(GenomeStream):
def __init__(self, genome_stream):
self.gs = c_void_p(gtlib.gt_gff3_out_stream_new(genome_stream, None))
self._as_parameter_ = self.gs
或设置restype
到 c_void_p
的子类,它会跳过调用 getfunc
.
class my_void_p(c_void_p):
pass
gtlib.gt_gff3_out_stream_new.restype = my_void_p
class GFF3OutStream(GenomeStream):
def __init__(self, genome_stream):
self.gs = gtlib.gt_gff3_out_stream_new(genome_stream, None)
self._as_parameter_ = self.gs # my_void_p instance
<小时/>
2.7.8 ctypes 源链接:
关于python - OS X 上的 Python ctypes '_as_parameter_' 和 'from_param' 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27067849/