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.)