1 module lib_handler;
2 
3 version(none):
4 
5 nothrow @nogc extern(C):
6 
7 import glob_opts;
8 //#include <ctype.h> // Needed for tolower functions
9 
10 import constants;
11 import util;
12 
13 version(Windows){
14 //#include <windows.h>
15 // todo
16 alias soHandle_t = HINSTANCE;
17 } else {
18 import core.stdc.ctype;
19 import core.sys.posix.dlfcn;
20 
21 alias soHandle_t = void *;
22 }
23 
24 version(Windows)
25 {
26     enum string SHAREDLIBEXT = "dll";
27 } else {
28     version(OSX){
29         enum string SHAREDLIBEXT = "dylib";
30     } else {
31     enum string SHAREDLIBEXT = "so";
32     }
33 }
34 
35 enum OSQP_NULL = null;
36 
37 soHandle_t lh_load_lib(const char *libName) {
38     soHandle_t h = OSQP_NULL;
39 
40     if (!libName) {
41         version(PRINTING){
42         c_eprint("ERROR in %s: no library name given\n", __FUNCTION__.ptr);
43         }
44         return OSQP_NULL;
45     }
46 
47 version(Windows){
48     h = LoadLibrary (libName);
49     if (!h) {
50         version(PRINTING){
51         c_eprint("ERROR in %s: Windows error while loading dynamic library %s, error = %d\n",
52                 __FUNCTION__.ptr, libName, cast(int)GetLastError());
53         }
54     }
55 } else {
56     h = dlopen (libName, RTLD_LAZY);
57     if (!h) {
58         version(PRINTING){
59         c_eprint("ERROR in %s: Error while loading dynamic library %s: %s\n", __FUNCTION__.ptr, libName, dlerror());
60         }
61     }
62 }
63 
64     return h;
65 } /* lh_load_lib */
66 
67 
68 c_int lh_unload_lib (soHandle_t h) {
69     c_int rc = 1;
70 
71 version (Windows){
72     rc = FreeLibrary (h);
73     rc = ! rc;
74 } else {
75     rc = dlclose (h);
76 }
77 
78     return rc;
79 } /* LSL_unLoadLib */
80 
81 
82 version (Windows){
83     alias symtype = FARPROC;
84 } else {
85     //typedef void* symtype;
86     alias symtype = void*;
87 }
88 /** Loads a symbol from a dynamically linked library.
89  * This function is not defined in the header to allow a workaround for the problem that dlsym returns an object instead of a function pointer.
90  * However, Windows also needs special care.
91  *
92  * The method does six attempts to load the symbol. Next to its given name, it also tries variations of lower case and upper case form and with an extra underscore.
93  * @param h Handle of dynamically linked library.
94  * @param symName Name of the symbol to load.
95  * @return A pointer to the symbol, or OSQP_NULL if not found.
96  */
97 symtype lh_load_sym (soHandle_t h, char *symName) {
98     symtype s;
99     char *from;
100     char *to;
101     char *tripSym;
102     char* err;
103     char [257] lcbuf;
104     char [257]ucbuf;
105     char [257]ocbuf;
106     size_t symLen;
107     int trip;
108 
109     s = OSQP_NULL;
110     err = OSQP_NULL;
111 
112     /* search in this order:
113      *  1. original
114      *  2. lower_
115      *  3. upper_
116      *  4. original_
117      *  5. lower
118      *  6. upper
119      */
120 
121     symLen = 0;
122     for (trip = 1;  trip <= 6;  trip++) {
123         switch (trip) {
124         case 1:                             /* original */
125             tripSym = cast(char*)symName;
126             break;
127         case 2:                             /* lower_ */
128             for (from = cast(char*)symName, to = cast(char*)lcbuf;  *from;  from++, to++) {
129                 *to = cast(char)tolower(*from); // todo : may cause data loss
130             }
131             symLen = from - symName;
132             *to++ = '_';
133             *to = '\0';
134             tripSym = cast(char*)lcbuf;
135             break;
136         case 3:                             /* upper_ */
137             for (from = cast(char*)symName, to = cast(char*)ucbuf;  *from;  from++, to++) {
138                 *to = cast(char)toupper(*from);
139             }
140             *to++ = '_';
141             *to = '\0';
142             tripSym = cast(char*)ucbuf;
143             break;
144         case 4:                             /* original_ */
145             c_strcpy(cast(char*)ocbuf, symName);
146             ocbuf[symLen] = '_';
147             ocbuf[symLen+1] = '\0';
148             tripSym = cast(char*)ocbuf;
149             break;
150         case 5:                             /* lower */
151             lcbuf[symLen] = '\0';
152             tripSym = cast(char*)lcbuf;
153             break;
154         case 6:                             /* upper */
155             ucbuf[symLen] = '\0';
156             tripSym = cast(char*)ucbuf;
157             break;
158         default:
159             tripSym = cast(char*)symName;
160         } /* end switch */
161 version(Windows){
162         s = GetProcAddress (h, tripSym);
163         if (s) {
164             return s;
165         } else {
166             version(PRINTING){
167             c_eprint("ERROR in %s: Cannot find symbol %s in dynamic library, error = %d\n", __FUNCTION__.ptr, 
168                     symName, cast(int)GetLastError());
169             }
170         }
171 } else {
172         s = dlsym (h, tripSym);
173         err = dlerror();  /* we have only one chance; a successive call to dlerror() returns OSQP_NULL */
174         if (err) {
175             version(PRINTING){
176             c_eprint("ERROR in %s: Cannot find symbol %s in dynamic library, error = %s\n", __FUNCTION__.ptr, 
177                     symName, err);
178             }
179         } else {
180             return s;
181         }
182 }
183     } /* end loop over symbol name variations */
184 
185     return OSQP_NULL;
186 } /* lh_load_sym */