Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 子类化ctypes指针-这段代码是如何工作的,我如何重写它?_Python_Ctypes - Fatal编程技术网

Python 子类化ctypes指针-这段代码是如何工作的,我如何重写它?

Python 子类化ctypes指针-这段代码是如何工作的,我如何重写它?,python,ctypes,Python,Ctypes,我正在使用pylibtiff库(托管),并尝试扩展类TIFF(ctypes.c\u void\u p)。我在使用以下方法时遇到问题: #lib已加载到libtiff.so或等效文件的路径 libtiff=ctypes.cdll.LoadLibrary(lib) 类别TIFF(ctypes.c\u void\u p): @类方法 def open(cls,文件名,mode='r'): “”“以tiff格式打开tiff文件。 """ tiff=libtiff.TIFFOpen(文件名,模式) 如果t

我正在使用
pylibtiff
库(托管),并尝试扩展
类TIFF(ctypes.c\u void\u p)
。我在使用以下方法时遇到问题:

#lib已加载到libtiff.so或等效文件的路径
libtiff=ctypes.cdll.LoadLibrary(lib)
类别TIFF(ctypes.c\u void\u p):
@类方法
def open(cls,文件名,mode='r'):
“”“以tiff格式打开tiff文件。
"""
tiff=libtiff.TIFFOpen(文件名,模式)
如果tiff.value为无:
raise TypeError('无法打开文件'+`filename'))
返回tiff
(全班)

现在,这里的预期使用模式是打开一个文件并接收一个
类TIFF
实例,如下所示:

class TIFFDifferent(TIFF):
    …
    @classmethod
    def open(cls, filename, mode='r'):
        tiff = libtiff.TIFFOpen(filename, mode)
        if tiff.value is None:
            raise TypeError ('Failed to open file '+`filename`)
        return cls(tiff)
class TIFFDifferent(TIFF):
    …
    @classmethod
    def open(cls, filename, mode='r'):
        stash = libtiff.TIFFOpen.restype
        libtiff.TIFFOpen.restype = cls
        tiff = libtiff.TIFFOpen(filename, mode)
        libtiff.TIFFOpen.restype = stash
        if tiff.value is None:
            raise TypeError ('Failed to open file '+`filename`)
        return tiff
导入libtiff
t=libtiff.TIFF.open('myfile.TIFF')
#例如,获取数据的numpy数组:
arr=t.读取图像()
这是什么魔法?libtiff
TIFF*
中的C变量如何回到pythonland并自动成为
类TIFF
实例?这大概与
ctypes.c\u void\u p

我这样做是因为我试图覆盖
类TIFF
上的一个方法:

导入libtiff
类别TIFF不同(libtiff.TIFF):
def read_图像(自身、详细=错误、不同=错误):
如果没有不同:
返回libtiff.TIFF.read_图像(self,verbose)
#我的不同代码。。。
但是,当我尝试创建一个
类TIFF different
实例时,我得到的是
类TIFF

[3]中的
:t=libtiffdifferent.TIFFdifferent.open('file.tiff'))
在[4]中:arr=t.read\u图像(different=True)
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在()
---->1 arr=t.read\u图像(不同=真)
TypeError:read_image()获得意外的关键字参数“different”
在[5]:t.read_图像?
类型:instancemethod
字符串形式:
文件:/Library/Python/2.7/site-packages/libtiff/libtiff_ctypes.py
定义:t.read_图像(self,verbose=False)
文档字符串:
从TIFF读取图像并将其作为数组返回。
In[6]:t
出[6]:

因此,我需要做的是重写
open
——如果不理解从C
TIFF*
到python
class TIFF
实例的神奇转换,我不知道如何做,而不需要构造函数、强制转换或任何其他显式操作。

神奇之处在于:

ctypes
文档中所述,您不必使用
ctypes
类型作为结果类型;您可以指定任何可调用的Python,通常是一个函数,它将验证实C返回值以引发异常,或者是一个类,它将实C返回值作为其构造函数参数

您可能会注意到
TIFF
类没有定义
\uuuu init\uuuu
方法。这就是继承自
c\u void\u p
的地方:您可以从指针构造
c\u void\u p
;因此,如果您有一个子类
c\u void\u p
,并且它不需要进行任何其他初始化,那么它可以依赖基类构造来处理它

因此,我需要做的是重写open,如果不理解从C
TIFF*
到python class
TIFF
实例的神奇转换,我不知道如何做,没有构造函数、cast或任何其他显式的东西

很明显,您可以在覆盖中执行显式构造调用,即使原始版本没有这样做:

def myopen(*args):
    tiffpointer = libtiff.cfunc(*args)
    return TIFF(tiffpointer)
但是,如果不能定义
libtiff.cfunc.restype
(例如,因为
pylibtiff
中的某些其他代码依赖于它返回不同的结果),则只需要这样做

不管怎样,我不确定这是你真正想要做的。你要做的是写这样的东西:

class TIFFDifferent(TIFF):
    …
    @classmethod
    def open(cls, filename, mode='r'):
        tiff = libtiff.TIFFOpen(filename, mode)
        if tiff.value is None:
            raise TypeError ('Failed to open file '+`filename`)
        return cls(tiff)
class TIFFDifferent(TIFF):
    …
    @classmethod
    def open(cls, filename, mode='r'):
        stash = libtiff.TIFFOpen.restype
        libtiff.TIFFOpen.restype = cls
        tiff = libtiff.TIFFOpen(filename, mode)
        libtiff.TIFFOpen.restype = stash
        if tiff.value is None:
            raise TypeError ('Failed to open file '+`filename`)
        return tiff
这是可行的,您根本不必理解
restype
背后的魔力。除非您担心构建一个短期的临时
TIFF
对象的成本(正如您所看到的,除了
c\u void\u p
之外,它没有成员,也没有构造函数代码),否则这还不够简单吗

还有一种可能性,我通常不会建议,在这里可能不合适,但可能是:如果
pylibtiff
的设计方式使得很难通过子类重写其行为,那么您可以(a)分叉代码并使用自己的版本,或者(b)在运行时使用monkeypatch。正如您在自己的评论中所建议的,类似这样的事情:

class TIFFDifferent(TIFF):
    …
    @classmethod
    def open(cls, filename, mode='r'):
        tiff = libtiff.TIFFOpen(filename, mode)
        if tiff.value is None:
            raise TypeError ('Failed to open file '+`filename`)
        return cls(tiff)
class TIFFDifferent(TIFF):
    …
    @classmethod
    def open(cls, filename, mode='r'):
        stash = libtiff.TIFFOpen.restype
        libtiff.TIFFOpen.restype = cls
        tiff = libtiff.TIFFOpen(filename, mode)
        libtiff.TIFFOpen.restype = stash
        if tiff.value is None:
            raise TypeError ('Failed to open file '+`filename`)
        return tiff

如果您的构造函数可能抛出异常,那么您可能希望将存储打包到
contextmanager
(或者使用
try:
/
finally:
)中;否则,您将使
重新键入
保持修补状态。

神奇之处在于:

ctypes
文档中所述,您不必使用
ctypes
类型作为结果类型;您可以指定任何可调用的Python,通常是一个函数,它将验证实C返回值以引发异常,或者是一个类,它将实C返回值作为其构造函数参数

您可能会注意到
TIFF
类没有定义
\uuuu init\uuuu
方法。这就是继承自
c\u void\u p
的地方:您可以从指针构造
c\u void\u p
;因此,如果您有一个子类
c\u void\u p
,并且它不需要进行任何其他初始化,那么它可以依赖基类构造来处理它

因此,我需要做的是重写open,如果不理解从C
TIFF*
到python类