Zebra. Zhang 2024-11-22 13:57 采纳率: 0%
浏览 168
已结题

python多进程调用DLL报错

基于python3.7,使用msl.loadlib中的两个库Client64和Server32实现了基于64位环境调用32位DLL的操作。单线程正常,但是在运行多进程时报错如下:ValueError: ctypes objects containing pointers cannot be pickled

查了资料,原因是ctypes指针无法被pickle模块序列化。因为在解析DLL函数时,使用了ctypes的指针:from ctypes import c_byte, c_int, c_short, c_ushort, pointer, c_char_p, byref。

 def calcKEY(self, seed_L1):
        """
        char* ipSeed,
        unsigned short sizeSeed,
        char* opKey,
        unsigned short maxSizeKey,
        unsigned short* opSizeKey
        :param seed_L1:
        :return:seedKey
        """
        bSeed = (c_byte * 4)(seed_L1[0], seed_L1[1], seed_L1[2], seed_L1[3])
        self.lib.ASAP1A_CCP_ComputeKeyFromSeed(pointer(bSeed), c_ushort(4), pointer(self.key), c_ushort(4), pointer(c_ushort(4)))
        seedKey = int.from_bytes(self.key, 'big', signed=False)
        return seedKey
  • 写回答

20条回答 默认 最新

  • 阿里嘎多学长 2024-11-22 14:08
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    python多进程调用DLL报错

    问题总结:在使用多进程时,调用DLL函数报错ValueError: ctypes objects containing pointers cannot be pickled,因为ctypes指针无法被pickle模块序列化。

    解决方案:由于ctypes指针无法被pickle模块序列化,因此不能使用多进程方式调用DLL函数。可以使用以下方法来解决问题:

    1. 使用fork方式rather than spawning new processes. This allows the child process to inherit the parent process's memory, including the DLL handles.
    import multiprocessing
    from multiprocessing import Process
    
    class Foo:
        def __init__(self):
            # Load the DLL here
            self.dll = self.load_dll()
    
        def load_dll(self):
            # Load the DLL using ctypes
            return ctypes.CDLL('path/to/dll.so')
    
        def run(self):
            # Call the DLL function
            self.dll.my_function()
    
    if __name__ == '__main__':
        foo = Foo()
        parent_process = multiprocessing.current_process()
        child_process = Process(target=foo.run)
        child_process.start()
        print("Parent process:", parent_process)
        print("Child process:", child_process)
        child_process.join()
    
    1. 使用共享内存来共享DLL handle。可以使用multiprocessing.Manager来创建共享内存,并在多进程下共享DLL handle。
    import multiprocessing
    
    class Foo:
        def __init__(self, dll):
            # Load the DLL here
            self.dll = dll
    
        def run(self):
            # Call the DLL function
            self.dll.my_function()
    
    if __name__ == '__main__':
        manager = multiprocessing.Manager()
        dll = manager.Value('c', ctypes.CDLL('path/to/dll.so'))
        foo = Foo(dll)
        parent_process = multiprocessing.current_process()
        child_process = Process(target=foo.run)
        child_process.start()
        print("Parent process:", parent_process)
        print("Child process:", child_process)
        child_process.join()
    
    1. 使用ipc通信来共享DLL handle。可以使用multiprocessing.Pipe来创建IPC通信管道,并在多进程下共享DLL handle。
    import multiprocessing
    
    class Foo:
        def __init__(self, dll):
            # Load the DLL here
            self.dll = dll
    
        def run(self):
            # Call the DLL function
            self.dll.my_function()
    
    if __name__ == '__main__':
        parent_process = multiprocessing.current_process()
        child_process = Process(target=foo.run)
        manager = multiprocessing.Manager()
        pipe = multiprocessing.Pipe()
        manager.connect(pipe)
        dll = manager.Value('c', ctypes.CDLL('path/to/dll.so'))
        foo = Foo(dll)
        child_process.start()
        print("Parent process:", parent_process)
        print("Child process:", child_process)
        child_process.join()
    

    以上三个方法都可以解决问题,但是可能存在其他的限制和限制。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月22日
  • 创建了问题 11月22日