lua-users home
lua-l archive

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


Is it possible to have my app statically link
to lua but also allow for DLL based packages
to work correctly?

Yes. But on Windows it's not as easy as on Linux (where you just use the linker's -E option to 'export all symbols' from the lua binary).

You need to build LUA.EXE with an export table for all of Lua's core and library API functions. Then you can build the DLLs you don't want to compile into LUA.EXE so that they import the Lua symbols from LUA.EXE, not from another DLL. (Note: this is important, or else your EXE will contain Lua, and your require()d DLLs will import _another_ Lua from your Lua DLL, or fail if you don't have one.)

luaconf.h includes some preprocessor stuff which allows to control what the special markers LUA_API and LUALIB_API are #defined to. When you tell the compiler to -DBUILD_AS_DLL, for example, these are #defined, on Windows, as __declspec(export) -- which tells the compiler to tell the linker that these symbols should be exported from any EXE or DLL they are build into.

Just be sure not to compile lua.c with BUILD_AS_DLL set -- when you do this it assumes that you want to create a stub which links to the DLL you are building, and #defines LUA_API to be __declspec(import).

This is not what you want. You want to build lua.c without marking the Lua core and API symbols for import, as you are building it statically into LUA.EXE, inside which the Lua core and API symbols _will behave as if in a DLL_, thus allowing your EXE to serve as both an EXE and (effectively) as a DLL.

I altered luaconf.h by wrapping all the prepocessor code which messes with LUA_API and LUALIB_API like this:

#ifndef LUA_API

# ifdef BUILD_AS_DLL /* whateveritwas*/
  . . .

# endif

#endif

and:

#ifndef LUACORE_API

# define LUALIB_API LUA_API /*I think it was */

#endif

Now I can control how the Lua core and lib symbols get treated whenever I build any of the components.

Of course, subsequently when you build DLLs you later want to require() (i.e. that you don't want to build in always) into your statically-linked LUA.EXE, you must ensure they are linked against LUA.EXE, not against the DLL version. This is because Windows binaries (EXE and DLL flavour) use import tables which define exactly which EXE/DLL to import what symbols from.

MinGW can link directly against DLLs (I believe it creates its own .def/.lib/.la file on the fly from the DLL's export table). But I don't believe it can dynamically link against an EXE. So you need to create a file to tell MinGW what symbols it can import from LUA.EXE.

Instructions for how to do this are given by Steve Donovan (in respect of SciTE.EXE rather than LUA.EXE, but the concept is identical) here:

http://lua-users.org/wiki/SciteLuaDll

in the section "Using MinGW DLLs without separate Lua DLL"

Create a lua.def file and use dlltool -d lua.def -l lua.la

and then link against lua.la -- that should do the trick.

I'd like to add support for sockets in my library
using the luasockets package.

I changed socket.c, and its luaopen_ function to "socketcore.c", and changed socket.lua to require "socketcore") (not "socket.core") to avoid the problem that luasocket assumes that the DLL part will be loaded from a subdirectory.

If you don't make this change, then luaopen_ing it yourself will put its functions in the table "socket", and will mark package.loaded.socket as equal to this table. This means you cannot later require the Lua part of socket (socket.lua) because the package system thinks it's already loaded. (When loaded dynamically, the socket\core.dll is put into the table "socket.core". The code doesn't take care of this when called directly as part of Lua's initialisation. This can be considered a bugette.)