| #include "lib_handler.h" |
| #include <ctype.h> // Needed for tolower functions |
| |
| #include "constants.h" |
| #include "util.h" |
| |
| soHandle_t lh_load_lib(const char *libName) { |
| soHandle_t h = OSQP_NULL; |
| |
| if (!libName) { |
| #ifdef PRINTING |
| c_eprint("no library name given"); |
| #endif |
| return OSQP_NULL; |
| } |
| |
| #ifdef IS_WINDOWS |
| h = LoadLibrary (libName); |
| if (!h) { |
| #ifdef PRINTING |
| c_eprint("Windows error while loading dynamic library %s, error = %d", |
| libName, (int)GetLastError()); |
| #endif |
| } |
| #else |
| h = dlopen (libName, RTLD_LAZY); |
| if (!h) { |
| #ifdef PRINTING |
| c_eprint("Error while loading dynamic library %s: %s", libName, dlerror()); |
| #endif |
| } |
| #endif |
| |
| return h; |
| } /* lh_load_lib */ |
| |
| |
| c_int lh_unload_lib (soHandle_t h) { |
| c_int rc = 1; |
| |
| #ifdef IS_WINDOWS |
| rc = FreeLibrary (h); |
| rc = ! rc; |
| #else |
| rc = dlclose (h); |
| #endif |
| |
| return rc; |
| } /* LSL_unLoadLib */ |
| |
| |
| #ifdef IS_WINDOWS |
| typedef FARPROC symtype; |
| #else |
| typedef void* symtype; |
| #endif |
| /** Loads a symbol from a dynamically linked library. |
| * 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. |
| * However, Windows also needs special care. |
| * |
| * 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. |
| * @param h Handle of dynamically linked library. |
| * @param symName Name of the symbol to load. |
| * @return A pointer to the symbol, or OSQP_NULL if not found. |
| */ |
| symtype lh_load_sym (soHandle_t h, const char *symName) { |
| symtype s; |
| const char *from; |
| char *to; |
| const char *tripSym; |
| char* err; |
| char lcbuf[257]; |
| char ucbuf[257]; |
| char ocbuf[257]; |
| size_t symLen; |
| int trip; |
| |
| s = OSQP_NULL; |
| err = OSQP_NULL; |
| |
| /* search in this order: |
| * 1. original |
| * 2. lower_ |
| * 3. upper_ |
| * 4. original_ |
| * 5. lower |
| * 6. upper |
| */ |
| |
| symLen = 0; |
| for (trip = 1; trip <= 6; trip++) { |
| switch (trip) { |
| case 1: /* original */ |
| tripSym = symName; |
| break; |
| case 2: /* lower_ */ |
| for (from = symName, to = lcbuf; *from; from++, to++) { |
| *to = tolower(*from); |
| } |
| symLen = from - symName; |
| *to++ = '_'; |
| *to = '\0'; |
| tripSym = lcbuf; |
| break; |
| case 3: /* upper_ */ |
| for (from = symName, to = ucbuf; *from; from++, to++) { |
| *to = toupper(*from); |
| } |
| *to++ = '_'; |
| *to = '\0'; |
| tripSym = ucbuf; |
| break; |
| case 4: /* original_ */ |
| c_strcpy(ocbuf, symName); |
| ocbuf[symLen] = '_'; |
| ocbuf[symLen+1] = '\0'; |
| tripSym = ocbuf; |
| break; |
| case 5: /* lower */ |
| lcbuf[symLen] = '\0'; |
| tripSym = lcbuf; |
| break; |
| case 6: /* upper */ |
| ucbuf[symLen] = '\0'; |
| tripSym = ucbuf; |
| break; |
| default: |
| tripSym = symName; |
| } /* end switch */ |
| #ifdef IS_WINDOWS |
| s = GetProcAddress (h, tripSym); |
| if (s) { |
| return s; |
| } else { |
| #ifdef PRINTING |
| c_eprint("Cannot find symbol %s in dynamic library, error = %d", |
| symName, (int)GetLastError()); |
| #endif |
| } |
| #else |
| s = dlsym (h, tripSym); |
| err = dlerror(); /* we have only one chance; a successive call to dlerror() returns OSQP_NULL */ |
| if (err) { |
| #ifdef PRINTING |
| c_eprint("Cannot find symbol %s in dynamic library, error = %s", |
| symName, err); |
| #endif |
| } else { |
| return s; |
| } |
| #endif |
| } /* end loop over symbol name variations */ |
| |
| return OSQP_NULL; |
| } /* lh_load_sym */ |