代码之家  ›  专栏  ›  技术社区  ›  Mike Sadler

Python:ctypes加载的dll是否共享相同的内存空间

  •  1
  • Mike Sadler  · 技术社区  · 6 年前

    我试图用Python中的DLL做一些事情,我知道我可以在C++中完成,但是我得到了内存异常。

    如果在C++中加载两个DLL并为它们提供相同的指针,则它们都可以对指针指向的对象进行操作,而不会出现问题。

    当使用Python和cytypes执行同样的操作时,创建对象的dll在随后的调用中完全可以取消对指针的引用, 所以指针在Python和C++ DLL之间的传递工作正常。 . 但是,当以相同的方式将此指针提供给第二个dll时,会出现一个非常不具信息性的异常: “WindowsError:异常:读取0x0101CC84时访问冲突” .

    ctypes dlls viewed in the debugger

    在我开始尝试调试这些DLL(这将是痛苦的)之前,有人知道Python是否将这些C++ DLL加载到相同的内存空间中?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Mark Tolonen    6 年前

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

    你可以 .argtypes restype 声明不正确(或者根本没有)。下面是一个有效的例子:

    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);
    }
    

    蟒蛇

    >>> 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传递到另一个DLL。

    像这样的工具 SysInternals Process Explorer 可用于查看进程空间中的dll:

    Process Explorer showing Python.exe and DLLs

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