lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


The patch below adds code so that Lua's loadlib can support the native
Mac/OSX DylD API for loading binary modules, instead of relying on the
dlcompat package, which is an optional add-on.  Adrian Perez and Asko
Kauppi wrote some code for this for the LuaX and luacheia projects,
and I have just trimmed it down to the minimum necessary to fit in
src/lib/loadlib.c.  I have tested it and it seems to work fine, but
more testing & review sure wouldn't hurt.

Also, the patch includes a small fix, via luacheia, for compiling the
dlopen code on OpenBSD.

Lua authors: please consider this patch for Lua 5.1 (or whatever the
next version is).  Here's the diff against the Lua 5.0 loadlib.c:

----
2c2
< ** $Id: loadlib.c,v 1.1 2003/07/18 05:35:37 tulrich Exp $
---
> ** $Id: loadlib.c,v 1.2 2003/12/27 16:21:51 tulrich Exp $
47a48,52
> /* OpenBSD apparently doesn't define RTLD_NOW */
> # ifndef RTLD_NOW
> #  define RTLD_NOW RTLD_LAZY
> # endif
> 
130a136,245
> #ifndef LOADLIB
> # if defined(__APPLE__) && defined(__MACH__)
> #  define USE_DYLD
> # endif
> #endif
> 
> 
> #ifdef USE_DYLD
> #define LOADLIB
> /*
>  * This code by Adrian Perez, Asko Kauppi & Thatcher Ulrich contains
>  * native OS X support for Lua's loadlib (without the need of the
>  * 'dlcompat' library).  The original code by Adrian Perez and Asko
>  * Kauppi is more modular and exposes a C API; Thatcher Ulrich has cut
>  * it down to the minimum necessary to implement loadlib().
>  * 
>  * The original code can be found in Asko Kauppi's LuaX project.
>  */
> 
> /*
>  * Small (and fast) wrapper around the Dyld API to dynamically load
>  * modules. Due to limitations in OSX's public APIs, only modules
>  * with a MH_BUNDLE header can be loaded; you can create one of
>  * these by passing the '-bundle' option to Apple's GCC when linking
>  * the module.
>  */
> 
> #include <mach-o/dyld.h>
> #include <string.h>   /* strlen() */
> 
> 
> static int loadlib(lua_State *L)
> {
>  const char *path=luaL_checkstring(L,1);
>  const char *init=luaL_checkstring(L,2);
> 
>  NSObjectFileImageReturnCode ret;
>  NSObjectFileImage nsimg;
>  NSModule nsmod;
> 
>  if (!path) return NULL;
> 
>  /* Load image from file:
>   */
>  ret = NSCreateObjectFileImageFromFile(path, &nsimg);
> 
>  if (ret != NSObjectFileImageSuccess)
>  {
>   /* Unable to load! */
>   lua_pushnil(L);
>   lua_pushstring(L, "failure in NSCreateObjectFileImageFromFile");
>   /* @@ would be good to get a real error msg from the OS */
>   lua_pushstring(L, "open");
>   return 3;
>  }
> 	
>  /* Link into the rest of the executable:
>   */
>  /* According to Apple's documentation, we can destroy the object image
>   * after linking it: although we instruct Dyld to do that, Dyld will
>   * keep it in memory as long as it is linked in the executable (i.e:
>   * until NSUnLinkModule() is called). 
>   *
>   * This way we can just return the NSModule after releasing the
>   * image.
>   */
>  nsmod = NSLinkModule(
>   nsimg,
>   path,
>   NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
>  NSDestroyObjectFileImage(nsimg);
>  if (!nsmod)
>  {
>   /* Unable to link! */
>   lua_pushnil(L);
>   lua_pushstring(L, "failure in NSLinkModule");	/* @@ would be good to get a real error msg from the OS */
>   lua_pushstring(L, "open");
>   return 3;
>  }
> 
>  {
>   NSSymbol nss;
>   /* tulrich: what the heck is going on here with the dynamically
>    * sized stack string?  Is this relying on a GCC extension? */
>   char real_name[ strlen(init) + 2 ]; 	/* '_'+init */
> 
>   real_name[0]='_';
>   strcpy( real_name+1, init );
>     
>   nss = NSLookupSymbolInModule(nsmod, real_name);
>   if (nss)
>   {
>    /* Success -- return the function */
>    lua_CFunction f = (lua_CFunction) NSAddressOfSymbol(nss);
>    lua_pushlightuserdata(L,nsmod);
>    lua_pushcclosure(L,f,1);
>    return 1;
>   }
>  }
> 
>  /* Couldn't find desired function. */
>  lua_pushnil(L);
>  lua_pushstring(L, "can't find function in library");	/* @@ would be good to get a real error msg from the OS */
>  lua_pushstring(L, "init");
>  return 3;
> }
>   
> #endif /* USE_DYLD */
> 
> 
----

-- 
Thatcher Ulrich
http://tulrich.com