blob: f3c8cca234f2467b9f8105d5a021937eedc4edf4 [file] [log] [blame]
Austin Schuh9049e202022-02-20 17:34:16 -08001#include "lib_handler.h"
2#include <ctype.h> // Needed for tolower functions
3
4#include "constants.h"
5#include "util.h"
6
7soHandle_t lh_load_lib(const char *libName) {
8 soHandle_t h = OSQP_NULL;
9
10 if (!libName) {
11 #ifdef PRINTING
12 c_eprint("no library name given");
13 #endif
14 return OSQP_NULL;
15 }
16
17#ifdef IS_WINDOWS
18 h = LoadLibrary (libName);
19 if (!h) {
20 #ifdef PRINTING
21 c_eprint("Windows error while loading dynamic library %s, error = %d",
22 libName, (int)GetLastError());
23 #endif
24 }
25#else
26 h = dlopen (libName, RTLD_LAZY);
27 if (!h) {
28 #ifdef PRINTING
29 c_eprint("Error while loading dynamic library %s: %s", libName, dlerror());
30 #endif
31 }
32#endif
33
34 return h;
35} /* lh_load_lib */
36
37
38c_int lh_unload_lib (soHandle_t h) {
39 c_int rc = 1;
40
41#ifdef IS_WINDOWS
42 rc = FreeLibrary (h);
43 rc = ! rc;
44#else
45 rc = dlclose (h);
46#endif
47
48 return rc;
49} /* LSL_unLoadLib */
50
51
52#ifdef IS_WINDOWS
53typedef FARPROC symtype;
54#else
55typedef void* symtype;
56#endif
57/** Loads a symbol from a dynamically linked library.
58 * 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.
59 * However, Windows also needs special care.
60 *
61 * 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.
62 * @param h Handle of dynamically linked library.
63 * @param symName Name of the symbol to load.
64 * @return A pointer to the symbol, or OSQP_NULL if not found.
65 */
66symtype lh_load_sym (soHandle_t h, const char *symName) {
67 symtype s;
68 const char *from;
69 char *to;
70 const char *tripSym;
71 char* err;
72 char lcbuf[257];
73 char ucbuf[257];
74 char ocbuf[257];
75 size_t symLen;
76 int trip;
77
78 s = OSQP_NULL;
79 err = OSQP_NULL;
80
81 /* search in this order:
82 * 1. original
83 * 2. lower_
84 * 3. upper_
85 * 4. original_
86 * 5. lower
87 * 6. upper
88 */
89
90 symLen = 0;
91 for (trip = 1; trip <= 6; trip++) {
92 switch (trip) {
93 case 1: /* original */
94 tripSym = symName;
95 break;
96 case 2: /* lower_ */
97 for (from = symName, to = lcbuf; *from; from++, to++) {
98 *to = tolower(*from);
99 }
100 symLen = from - symName;
101 *to++ = '_';
102 *to = '\0';
103 tripSym = lcbuf;
104 break;
105 case 3: /* upper_ */
106 for (from = symName, to = ucbuf; *from; from++, to++) {
107 *to = toupper(*from);
108 }
109 *to++ = '_';
110 *to = '\0';
111 tripSym = ucbuf;
112 break;
113 case 4: /* original_ */
114 c_strcpy(ocbuf, symName);
115 ocbuf[symLen] = '_';
116 ocbuf[symLen+1] = '\0';
117 tripSym = ocbuf;
118 break;
119 case 5: /* lower */
120 lcbuf[symLen] = '\0';
121 tripSym = lcbuf;
122 break;
123 case 6: /* upper */
124 ucbuf[symLen] = '\0';
125 tripSym = ucbuf;
126 break;
127 default:
128 tripSym = symName;
129 } /* end switch */
130#ifdef IS_WINDOWS
131 s = GetProcAddress (h, tripSym);
132 if (s) {
133 return s;
134 } else {
135 #ifdef PRINTING
136 c_eprint("Cannot find symbol %s in dynamic library, error = %d",
137 symName, (int)GetLastError());
138 #endif
139 }
140#else
141 s = dlsym (h, tripSym);
142 err = dlerror(); /* we have only one chance; a successive call to dlerror() returns OSQP_NULL */
143 if (err) {
144 #ifdef PRINTING
145 c_eprint("Cannot find symbol %s in dynamic library, error = %s",
146 symName, err);
147 #endif
148 } else {
149 return s;
150 }
151#endif
152 } /* end loop over symbol name variations */
153
154 return OSQP_NULL;
155} /* lh_load_sym */