aboutsummaryrefslogtreecommitdiff
path: root/loadlib.c
blob: 5dcc4ccdbd13fa66effe2608e3d5bc670f267bb3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
** $Id: loadlib.c,v 1.2 2003/03/18 12:25:01 roberto Exp roberto $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
*
* This  Lua library  exports a  single function,  called loadlib,  which is
* called from Lua  as loadlib(lib,init), where lib is the  full name of the
* library to be  loaded (including the complete path) and  init is the name
* of a function  to be called after the library  is loaded. Typically, this
* function will register other functions,  thus making the complete library
* available  to Lua.  The init  function is  *not* automatically  called by
* loadlib. Instead,  loadlib returns  the init function  as a  Lua function
* that the client  can call when it  thinks is appropriate. In  the case of
* errors,  loadlib  returns  nil  and two  strings  describing  the  error.
* The  first string  is  supplied by  the operating  system;  it should  be
* informative and useful  for error messages. The second  string is "open",
* "init", or  "absent" to identify  the error and is  meant to be  used for
* making  decisions without  having to  look into  the first  string (whose
* format is system-dependent).
*
* This module contains  an implementation of loadlib for  Unix systems that
* have dlfcn, an implementation for Windows,  and a stub for other systems.
* See  the list  at  the end  of  this  file for  some  links to  available
* implementations of dlfcn  and interfaces to other  native dynamic loaders
* on top of which loadlib could be implemented.
*
*/

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

#ifndef USE_LOADLIB
#define USE_LOADLIB 1
#endif

#ifndef USE_DLOPEN
#define USE_DLOPEN 0
#endif

#if USE_LOADLIB

#if defined(linux) || defined(sun) || defined(sgi) || defined(BSD) || USE_DLOPEN
#define LOADLIB
/*
* This is an implementation of loadlib based on the dlfcn interface.
* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
* NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least
* as an emulation layer on top of native functions.
*/

#include <dlfcn.h>

static int loadlib(lua_State *L)
{
 const char *path=luaL_checkstring(L,1);
 const char *init=luaL_checkstring(L,2);
 void *lib=dlopen(path,RTLD_NOW);
 if (lib!=NULL)
 {
  lua_CFunction f=(lua_CFunction) dlsym(lib,init);
  if (f!=NULL)
  {
   lua_pushlightuserdata(L,lib);
   lua_pushcclosure(L,f,1);
   return 1;
  }
 }
 lua_pushnil(L);
 lua_pushstring(L,dlerror());
 lua_pushstring(L,(lib!=NULL) ? "init" : "open");
 if (lib!=NULL) dlclose(lib);
 return 3;
}

#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#define LOADLIB
/*
* This is an implementation of loadlib for Windows using native functions.
*/

#include <windows.h>

static void pusherror(lua_State *L)
{
 int error=GetLastError();
 char buffer[128];
 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
	0, error, 0, buffer, sizeof(buffer), 0))
  lua_pushstring(L,buffer);
 else
  lua_pushfstring(L,"system error %d\n",error);
}

static int loadlib(lua_State *L)
{
 const char *path=luaL_checkstring(L,1);
 const char *init=luaL_checkstring(L,2);
 HINSTANCE lib=LoadLibrary(path);
 if (lib!=NULL)
 {
  lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init);
  if (f!=NULL)
  {
   lua_pushlightuserdata(L,lib);
   lua_pushcclosure(L,f,1);
   return 1;
  }
 }
 lua_pushnil(L);
 pusherror(L);
 lua_pushstring(L,(lib!=NULL) ? "init" : "open");
 if (lib!=NULL) FreeLibrary(lib);
 return 3;
}

#else
/*
* write an implementation for your system  here and send it to us, together
* with preprocessing symbols that identify your system.
*/
#endif
#endif

#ifndef LOADLIB
/* Fallback for other systems */

static int loadlib(lua_State *L)
{
 lua_pushnil(L);
 lua_pushliteral(L,"`loadlib' not supported");
 lua_pushliteral(L,"absent");
 return 3;
}
#endif

LUALIB_API int luaopen_loadlib (lua_State *L)
{
 lua_register(L,"loadlib",loadlib);
 return 0;
}

/*
* Here  are  some links  por  to  available  implementations of  dlfcn  and
* interfaces to other native dynamic loaders  on top of which loadlib could
* be implemented. Please send contributions and corrections to us.
*
* AIX
* Starting with AIX 4.2, dlfcn is included in the base OS.
* There is also an emulation package available.
* http://www.faqs.org/faqs/aix-faq/part4/section-21.html
*
* HPUX 
* HPUX 11 has dlfcn. For HPUX 10 use shl_*.
* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html
* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html
*
* Macintosh, Windows
* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html
*
* Mac OS X/Darwin
* http://www.opendarwin.org/projects/dlcompat/
*
* GLIB has wrapper code for BeOS, OS2, Unix and Windows
* http://cvs.gnome.org/lxr/source/glib/gmodule/
*
*/