[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- From: Duck <duck@...>
- Date: Thu, 6 Dec 2007 07:57:16 +1100 (EST)
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.)