Python ctypes : WindowsError when using function pointer

标签 python windows ctypes dokan

我正在尝试使用 Python 的 ctypes 来处理 DLL,但是当我尝试调用作为指向另一个函数的指针传递的函数时,我偶尔会遇到问题。

一点背景...我正在尝试使用 Dokan 构建用户空间文件系统(版本 0.6.0)。稍微松散地说,Dokan 基本上是 FUSE适用于 Windows。我已经使用 ctypes 包装了 dokan 头文件(类似于 pydokan )。该头文件包含如下所示的函数指针定义

typedef int (WINAPI *PFillFindData) (PWIN32_FIND_DATAW, PDOKAN_FILE_INFO);

它还包含另一个函数的原型(prototype)

int (DOKAN_CALLBACK *FindFilesWithPattern) (
     LPCWSTR,
     LPCWSTR,
     PFillFindData,
     PDOKAN_FILE_INFO);

相应的 ctypes 定义如下所示

PFillFindData = ctypes.WINFUNCTYPE(ctypes.c_int,
                                   PWIN32_FIND_DATAW, 
                                   PDOKAN_FILE_INFO)

FindFilesWithPattern = ctypes.WINFUNCTYPE(ctypes.c_int,
                                          ctypes.c_wchar_p,
                                          ctypes.c_wchar_p,
                                          PFillFindData,
                                          PDOKAN_FILE_INFO)

后一个函数 (FindFilesWithPattern) 的实现必须调用传递给它的 FillFindData 函数。一个基本的实现看起来像这样

def FindFilesWithPattern(self,
                         FileName,
                         SearchPattern,
                         FillFindData,
                         DokanFileInfo):
    if FileName == '\\':
        File = WIN32_FIND_DATAW(FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_READONLY, 
                                FILETIME(1, 1),
                                FILETIME(1, 1), 
                                FILETIME(1, 1), 
                                0, 
                                len(self.HelloWorldText), 
                                0, 
                                0, 
                                'Hello_World.txt',
                                'Hello_~1.txt')
        pFile = PWIN32_FIND_DATAW(File)
        FillFindData(pFile, DokanFileInfo)
        return 0
    else:
        return -ERROR_FILE_NOT_FOUND

调用此函数时,我偶尔会遇到以下错误:

Traceback (most recent call last):
    File "_ctypes/callbacks.c", line 313, in 'calling callback function'
    File "src/test.py", line 385, in FindFilesWithPattern
        FillFindData(pFile, DokanFileInfo)
WindowsError: exception: access violation reading 0x0000000000000008

我很生气。乍一看,我似乎在尝试访问超出范围的内存。但这个错误只是偶尔发生。有时一切正常,结果如预期般返回。 (澄清一下,当我说偶尔时,我的意思是错误发生在程序的某些运行而不是其他程序上。错误似乎在单次运行中持续发生或不发生。)

然后我想知道是否我得到的是错误代码而不是内存地址。我找到了 here 如果这是一个错误代码,那么它可能表示“内存不足”。当我查看系统监视器时,这似乎不是问题。我试过运行各种内存分析器,如 HeapyMeliae ,但它们似乎都不适用于 Windows 64 位上的 Python 2.7。

我的下一个最佳猜测是这是使用 64 位操作系统的问题。也许用于函数指针的类型不足以正确处理它。在谷歌搜索之后,似乎其他人在 Win64 中使用 ctypes 时遇到了问题。我已经为 64 位架构构建了我的 Dokan 库。那我的python代码有问题吗?

如有任何帮助,我们将不胜感激。我已经为此苦苦挣扎了一段时间。

可以找到类似的帖子here .不过,这似乎并不十分相似。

注意:在 python 代码中,您会看到一些未在此处定义的类型(例如 PDOKAN_FILE_INFO)。这些要么是结构,要么是指向结构的指针,为了简洁起见,我没有包括在内。

最佳答案

如何实例化和使用回调?回调必须在其可能被调用的生命周期内保留在范围内。参见 this answer .这些


编辑

澄清我认为的问题是...

我看到您必须实现一个 DOKAN_OPERATIONS 结构,该结构实现回调,例如 FindFilesWithPattern,然后使用该结构调用 DokanMain 以挂载文件系统。填写结构时,您应该为回调创建类型,然后使用 Python 函数实例化回调。类似于(伪代码):

#Create the callback pointer type
PFINDFILESWITHPATTERN = ctypes.WINFUNCTYPE(ctypes.c_int,
                                          ctypes.c_wchar_p,
                                          ctypes.c_wchar_p,
                                          PFillFindData,
                                          PDOKAN_FILE_INFO) 

# Implement in Python
def FindFilesWithPatternImpl(...):
    # implementation

# Create a callback pointer object
FindFilesWithPattern = PFINDFILESIWTHPATTERN(FindFilesWithPatternImpl)

# Create the required structure listing the callback
dokan_op = DOKAN_OPERATIONS(...,FindFilesWithPattern,...)

# Register the callbacks
DokanMain(byref(dokan_op))

在可以使用回调的生命周期内,您必须保留对对象 dokan_op 的引用。如果您实现类似于以下的安装 Dokan:

def mount():
    # Create structure locally
    dokan_op = DOKAN_OPERATIONS(...)
    # Spin off thread to mount Dokan
    threading.Thread(DokanMain,args=(byref(dokan_op),))

mount()

一旦mount()返回,dokan_op就会被销毁。这是我原来的回答所描述的场景,会导致您看到的错误。我正在对您的问题进行理论化,因为我不知道其余代码是什么样的,但我认为您在 Python 中实现 FindFilesWithPattern 的方式是正确的,尤其是。因为你说它间歇性地工作。我遇到过您之前看到的故障,上述情况或类似情况导致您看到的错误。

希望这有助于...

关于Python ctypes : WindowsError when using function pointer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6333340/

相关文章:

c++ - 在自定义源和 SmartTee 之间插入过滤器会泄漏 COM 对象

windows - 如果 JAVA_HOME 变量指向带有空格的路径,是否应该包含引号?

python - 如何将结构内部的 numpy 数组传递给 ctypes 函数?

python - 将客户端授权证书发送到 HTTPS 站点 - Python

python - Github Actions Build - 在多个文件夹上推送到 ECR

python - 在 Python 中打开 SSL 套接字连接

Python int 在调用 ctypes 函数时溢出

python - PyQt5 QListWidget 带有复选框和拖放

linux - 我无法从 Windows 主机访问在 VM 上运行的 Django 服务器

python - 带有回调 : access violation on exit 的 ctypes