【问题标题】:Python: do dlls loaded by ctypes share the same memory spacePython:ctypes加载的dll是否共享相同的内存空间
【发布时间】:2018-08-03 07:54:34
【问题描述】:

我正在尝试用 Python 中的 dll 做一些我知道我可以在 C++ 中做的事情,但是我遇到了内存异常。

如果你在 C++ 中加载两个 dll 并为它们提供相同的指针,它们都可以毫无问题地对指针指向的对象进行操作。

当使用 Python 和 cytypes 做同样的事情时,创建对象的 dll 绝对可以在后续调用中取消引用该指针,因此该指针在 Python 和 C++ dll 之间的传递工作正常 .但是,当以同样的方式将此指针提供给第二个 dll 时,我得到了一个非常无意义的异常:"WindowsError: exception: access violation reading 0x0101CC84".

在我开始尝试调试这些 dll(这会很痛苦)之前,有谁知道 Python 是否将这些 C++ dll 加载到同一个内存空间中?

【问题讨论】:

    标签: python c++ dll ctypes shared-memory


    【解决方案1】:

    是的,python.exe就是进程,所有的DLL都加载到它的内存空间中。

    您的.argtypesrestype 可能声明不正确(或根本没有声明)。这是一个有效的示例:

    x.c

    __declspec(dllexport) const char* func1()
    {
        return "hello";
    }
    

    y.c

    #include <stdio.h>
    
    __declspec(dllexport) void func2(const char* s)
    {
        printf("%s\n",s);
    }
    

    Python

    >>> from ctypes import *
    >>> x = CDLL('x')
    >>> x.func1.argtypes = None
    >>> x.func1.restype = c_void_p
    >>> y = CDLL('y')
    >>> y.func2.argtypes = [c_void_p]
    >>> y.func2.restype = None
    >>> s = x.func1()
    >>> hex(s)
    '0x7ff8b4ca8000'
    >>> y.func2(s)
    hello
    

    注意我明确声明了参数c_void_p,因为ctypes 将在输出时将c_char_p 转换为Python 字符串,在输入时从Python 字符串转换为char*,因此它不能证明同一个指针可以从一个 DLL 传递到另一个。

    SysInternals Process Explorer 之类的工具可用于查看进程空间中的 DLL:

    注意x.func1()返回的地址在x.dll的映射范围内,y.func2(s)正确显示。

    【讨论】:

    • 请问你是怎么发现这个的,@Mark Tolonen?
    • @MikeSadler 阅读 Windows Internals,或使用 SysInternals Process Explorer 等工具亲自查看。
    • @MikeSadler 可能的问题是您没有为您调用的函数正确声明 argtypes 和 restype。这对于指针和 64 位操作系统尤其重要,因为参数默认作为 int 传递,它们是 32 位的。我将更新一个工作示例...
    猜你喜欢
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 2010-11-13
    • 1970-01-01
    相关资源
    最近更新 更多