Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_module.c

open a shared library at runtime, find a symbol, call it

open a shared library at runtime, find a symbol, call it

Author
Castagnier Mickael
Version
1.0
Date
24/09/2026

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().

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "nilorea/n_log.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);
} 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;
if (parse_args(argc, argv) != 0) {
fprintf(stderr, "usage: %s [-V LOGLEVEL]\n", argv[0]);
return 2;
}
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;
}
static int failures
Definition ex_atlas.c:51
int main(void)
Definition ex_atlas.c:117
static void expect_true(const char *label, int cond)
Definition ex_atlas.c:53
static int log_level
#define EX_SYMBOL
a function whose answer is known
Definition ex_module.c:36
static int parse_args(int argc, char **argv)
read -V LOGLEVEL
Definition ex_module.c:53
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_ERR
error conditions
Definition n_log.h:100
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
Definition n_log.c:123
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:104
#define LOG_INFO
informational
Definition n_log.h:106
const char * n_module_extension(void)
The file extension shared libraries have on this platform.
Definition n_module.c:161
int n_module_close(N_MODULE **module)
Close a library and free its handle.
Definition n_module.c:136
void * n_module_symbol(N_MODULE *module, const char *name)
Find a symbol in an opened library.
Definition n_module.c:110
const char * n_module_error(void)
What the system said about this thread's last failed call.
Definition n_module.c:157
Common headers and low-level functions & define.
Generic log system.
an opened shared library
Definition n_module.c:40
Load a shared library at runtime and find its symbols.