Saturday, 6 November 2010

Lupa on OS X with MacPorts Python 2.6

Lupa doesn't Just Work on OS X 10.6 stock Python nor on MacPorts Python 2.6; it fails with:

Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import lupa
>>> from lupa import LuaRuntime
>>> lua = LuaRuntime()
Segmentation fault


LuaJIT seems to depend on being mapped within a certain address window (not sure why). The install page mentions that you have to use these linker options on any binary that embeds LuaJIT:
-pagezero_size 10000 -image_base 100000000

to satisfy this requirement. Neither Snow Leopard's nor MacPorts' Python uses those flags (why would they?) so you need a modified Python in order to support the lupa binary module. If you build your own Python from source, it's simply:
./configure LIBS="-pagezero_size 10000 -image_base 100000000"

In MacPorts it's a simple edit to the Portfile; for Python 2.6 (MacPorts package python26) I changed the file /opt/local/var/macports/sources/rsync.macports.org/release/ports/lang/python26/Portfile like so:

configure.args --enable-framework=${frameworks_dir} \
--enable-ipv6

became:

configure.args --enable-framework=${frameworks_dir} \
--enable-ipv6 \
LIBS="-pagezero_size 10000 -image_base 100000000"


After installing lupa, if you get:

Python 2.6.6 (r266:84292, Nov 6 2010, 10:18:50)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import lupa
Traceback (most recent call last):
File "", line 1, in
File "lupa/__init__.py", line 25, in
from lupa._lupa import *
ImportError: No module named _lupa
>>>

then check you're not still in the lupa source directory; Python picks up the lupa subdirectory from the source tree which has no binary module.

While I was poking around I also noticed lupa has a bug in its __init__.py relating to loading binary lua modules. Instead of:
import DLFCN

use:
import ctypes

Instead of:
sys.setdlopenflags(DLFCN.RTLD_NOW|DLFCN.RTLD_GLOBAL)

use:
sys.setdlopenflags(ctypes.RTLD_GLOBAL)


Perhaps one day somebody will write a Lua implementation in pure Python. I wouldn't care if it was dog-slow. Lua has become the de facto embeddable scripting language, and the lower the barrier to embedding, the better — even when embedding into existing scripting languages :)

No comments:

Post a Comment