使用带有32位库的python ctypes

时间:2016-04-06 09:51:06

标签: python ctypes

当我尝试导入一个加载32位库的简单ctype模块时,我得到:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "simple_test.py", line 5, in <module>
    _myLib = ctypes.CDLL(_path + _file)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 353, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: ../../bin/mylib.so: wrong ELF class: ELFCLASS32

也发生在python 3.3上。

这里的问题是我不想将我的lib重新编译为64位, 有没有办法让它发挥作用?

谢谢, 凯伦

2 个答案:

答案 0 :(得分:2)

您根本无法将32位代码加载到64位应用程序中,反之亦然。您的选择是:

  1. 交换使用32位解释器
  2. 继续使用64位解释器,但使用multiprocessing以便允许64位解释器与32位解释器通信。
  3. 将32位库重新编译为64位库
  4. 前两个选项遇到问题,基于debian的发行版使用包管理器无法同时安装32位解释器和64位解释器(参见eryksun的评论)。 p>

    重新编译库几乎肯定是更容易的选择,并且绝对不会遭受运行时开销。

    如何编号(2)的示例。预先警告,如果您经常使用这些方法或使用大输入/输出,这将导致来回发送数据的高额开销。

    main.py

    # example using the standard c library
    from subprocess import Popen, PIPE 
    from multiprocessing.managers import BaseManager
    import atexit
    
    p = Popen(["/path/to/32-bit/python", "/path/to/delegate.py"], stdout=PIPE)
    
    atexit.register(p.terminate)
    
    port = int(p.stdout.readline())
    authkey = p.stdout.read()
    
    m = BaseManager(address=("localhost", port), authkey=authkey)
    m.connect()
    
    # tell manager to expect an attribute called LibC
    m.register("LibC")
    
    # access and use libc
    libc = m.LibC()
    print(libc.abs(-2))
    

    delegate.py

    from multiprocessing.managers import BaseManager
    from ctypes import c_int, cdll
    from os import closerange, write
    
    # setup library
    libc = cdll.LoadLibrary("libc.so.6")
    
    # tell ctypes how to call function
    libc.abs.argtypes = c_int,
    libc.abs.restype = c_int
    
    # wrapper for access to the functions
    class LibC:
        abs = staticmethod(libc.abs)
    
    # setup manager
    manager = BaseManager(address=("localhost", 0))
    manager.register("LibC", LibC)
    
    server = manager.get_server()
    # tell caller the port and auth key to access the manager with
    write(1, str(server.address[1]).encode("ascii"))
    write(1, b"\n")
    write(1, server.authkey) # write raw authkey bytes
    closerange(0, 3) # close stdin, stdout, stderr
    
    server.serve_forever()
    

答案 1 :(得分:1)

您还可以使用(相对)新的MSL-LoadLib

它基本上是Dunes用他的例子描述的,但是捆绑了一个python32,所以你不必处理它。