Table of Contents
ex_module.c
open a shared library at runtime, find a symbol, call it Opens the system maths library (kernel32 on Windows), finds a function in it and calls it, then checks the failures: a library that is not there, a symbol the library does not have, and closing twice. Each failure must leave a reason in n_module_error(). ```c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>
#include "nilorea/n_common.h" #include "nilorea/n_log.h" #include "nilorea/n_module.h"
#if defined(windows) #define EX_LIBRARY "kernel32.dll" #define EX_SYMBOL "GetTickCount" #elif defined(APPLE) #define EX_LIBRARY "libSystem.dylib" #define EX_SYMBOL "cos" #else #define EX_LIBRARY "libm.so.6" #define EX_SYMBOL "cos" #endif
static int log_level = LOG_ERR; static int failures = 0;
static void expect_true(const char* what, int ok) { if (!ok) { n_log(LOG_ERR, "FAIL: %s", what); failures++; } else { n_log(LOG_INFO, "ok: %s", what); } }
static int parse_args(int argc, char** argv) { int opt = 0;
while ((opt = getopt(argc, argv, "V:")) != -1) {
if (opt == 'V') {
log_level = atoi(optarg);
} else {
return -1;
}
}
return 0;
}
int main(int argc, char** argv) { N_MODULE* module = NULL; void* symbol = NULL;
set_log_level(LOG_ERR);
if (parse_args(argc, argv) != 0) {
fprintf(stderr, "usage: %s [-V LOGLEVEL]\n", argv[0]);
return 2;
}
set_log_level(log_level);
expect_true("the extension is not empty", n_module_extension()[0] != '\0');
expect_true("no error before any call", n_module_error()[0] == '\0');
module = n_module_open(EX_LIBRARY);
expect_true("the system library opens", module != NULL);
if (module) {
symbol = n_module_symbol(module, EX_SYMBOL);
expect_true("its function is found", symbol != NULL);
#if !defined(windows) if (symbol) { double (*fn)(double) = NULL;
memcpy((void*)&fn, (const void*)&symbol, sizeof(fn));
expect_true("calling it gives cos(0) = 1", fn(0.0) == 1.0);
}
#endif expect_true("a missing symbol is NULL", n_module_symbol(module, "n_module_no_such_symbol") == NULL); expect_true("and says why", n_module_error()[0] != '\0'); expect_true("a found symbol clears the error", n_module_symbol(module, EX_SYMBOL) != NULL && n_module_error()[0] == '\0'); expect_true("close succeeds", n_module_close(&module) == TRUE); expect_true("close sets the handle to NULL", module == NULL); } expect_true("closing NULL is a no-op", n_module_close(&module) == TRUE); expect_true("closing a NULL address is a no-op", n_module_close(NULL) == TRUE);
module = n_module_open("n_module_no_such_library.so");
expect_true("a missing library is NULL", module == NULL);
expect_true("and says why", n_module_error()[0] != '\0');
n_log(LOG_INFO, "the reason given: %s", n_module_error());
if (failures) {
n_log(LOG_ERR, "%d check(s) failed", failures);
return 1;
}
n_log(LOG_NOTICE, "all module checks passed");
return 0;
}
_Filename: ex_module.c_
Modules
- AABB3D
- ACCEPT_POOL
- ALLEGRO4
- ALLEGRO5
- ANIM_LIB
- ASTAR
- ATLAS_LIB
- AVRO
- CLOCK_SYNC
- COMMONS
- CONFIGFILE
- CYPHER_BASE64
- CYPHER_VIGENERE
- DEAD_RECKONING
- ENUMS
- EXCEPTIONS
- GAME_ENV
- GIT
- GUI
- HASH_TABLE
- ISOMETRIC_ENGINE
- LIST
- LOG
- LOGNODUP
- LZ4
- NETWORKING
- NETWORK_MSG
- N_COOKIES
- N_DIFF
- N_DIGEST
- N_DISK_CACHE
- N_DNS
- N_ECC
- N_ENTROPY
- N_FILES
- N_FLUIDS
- N_GUI_COLOR
- N_GUI_COLORWHEEL
- N_GUI_CURVE
- N_GUI_GRID
- N_GUI_POPUP
- N_HEX
- N_HTTP3
- N_HTTP_COOKIE
- N_HTTP_FORM
- N_HTTP_MIME
- N_HTTP_REQ
- N_HTTP_RESP
- N_HTTP_ROUTER
- N_HTTP_SERVER
- N_ICC
- N_JSON
- N_KAFKA
- N_LINALG
- N_MODULE
- N_OPENSSL_COMPAT
- N_PRETTY
- N_PTH
- N_QUERY
- N_RANDOM
- N_SHA256
- N_STR
- N_TIFF
- N_TIME
- N_USER
- N_X509
- N_ZIP
- PARTICLES
- PCRE
- PHYSICS
- SIGNALS
- STACK
- THREADS
- TRAJECTORY
- TREE
- ZLIB