6 ex__module_8c
gullradriel edited this page 2026-10-09 00:55:18 +02:00

examples/ex_module.c

Functions

Name
int parse_args(int argc, char ** argv)
read -V LOGLEVEL
int main(int argc, char ** argv)
void expect_true(const char * what, int ok)
record one check

Attributes

Name
int log_level
int failures

Defines

Name
EX_SYMBOL
a function whose answer is known
EX_LIBRARY
the maths library, by its versioned name: the unversioned .so is a development symlink a runtime system may not have

Functions Documentation

function parse_args

static int parse_args(
    int argc,
    char ** argv
)

read -V LOGLEVEL

function main

int main(
    int argc,
    char ** argv
)

function expect_true

static void expect_true(
    const char * what,
    int ok
)

record one check

Attributes Documentation

variable log_level

static int log_level = 3;

variable failures

static int failures = 0;

Macros Documentation

define EX_SYMBOL

#define EX_SYMBOL "cos"

a function whose answer is known

define EX_LIBRARY

#define EX_LIBRARY "libm.so.6"

the maths library, by its versioned name: the unversioned .so is a development symlink a runtime system may not have

Source code



#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;
}