Reputation: 119
When I try to import a simple ctype module that loads a 32bit library I get:
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
also happens with python 3.3.
The issue here is that I DON'T want to re-compile my lib as 64bit, is there a way I can make it work?
Thanks, Keren
Upvotes: 5
Views: 8650
Reputation: 423
There is also the (relatively) new MSL-LoadLib that you could use.
Its basically what Dunes describe with his example, but comes bundled with a python32, so you don't have to deal with that.
Upvotes: 4
Reputation: 40713
You simply cannot load 32-bit code into a 64-bit application, and vice versa. Your options are:
multiprocessing
so as to allow your 64-bit interpreter to communicate with the 32-bit interpreter.The first two options suffer from the problem, that on debian-based distributions 32-bit interpreters and 64-bit interpreters cannot be installed at the same time using the package manager (see eryksun's comment).
Recompiling the library is almost certainly to be the easier option, and definitely don't suffer a runtime overhead.
An example of how to do number (2). Be forewarned this will incur high overheads for sending data back and forth if you are using these methods a lot, or with large inputs/outputs.
# 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))
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()
Upvotes: 3