Platform-neutral API for system level and libc-like functions


It has its roots in netscape (Netscape Portable Runtime) as the platform independent layer of java. It is used by mozilla in the firefox web browser. It is plain C and crossplatform, with threading, processes, sockets, file systems etc.


What is it?

Platform abstraction.

How cool is it?



APR, Boost.

When to use it?

When you want to write portable code with not to much hassle.

Is it dead?

Nope, it is still under active development and used in firefox.

Where is it?


How to use it

The documentation is rather sparse, outdated and full with linkrot. But the library is rather impressive.


file: 1_download.sh


mkdir -p tmp
cd ./tmp
wget -q https://ftp.mozilla.org/pub/nspr/releases/v4.14/src/nspr-4.14.tar.gz
tar -xaf nspr-4.14.tar.gz
cd nspr-4.14/nspr
./configure --enable-ipv6  --enable-64bit --enable-strip --disable-debug --enable-optimize=-O2 


The init and shutdown process is optional, but to avoid valgrind messages it is better to be explicit.

file: init.c

#include <prinit.h>

int main(const int argc, const char ** argv) {
    //stuff goes here
    PRStatus PR_Cleanup(void);

file: 2_compile.sh


clang \
    -Wall -Wextra -Weverything \
        -Wno-unused-parameter \
        -Wno-reserved-id-macro \
    init.c \
    -o ./tmp/init \
    -I./tmp/nspr-4.14/nspr/dist/include/nspr/ \
    -L./tmp/nspr-4.14/nspr/dist/lib/  -lnspr4 -lplc4 -lplds4

Readable return codes

file: returns.c

#include <prtypes.h>

PRStatus some_complex_function() {
    PRStatus status;

    status = PR_SUCCESS;
    if ( 1 /* || somecodition */) {
        return PR_Failure;
    return status;

int main(const int argc, const char ** argv) {
    PRStatus status;

    status = some_complex_function();

    return (status == PR_SUCCESS) ? 0 : 1;

This simple convention makes it readable what the function return codes actually mean.

Memory operations

file: memory.c

#include <prmem.h>

typedef struct _something_t {
    int    x;
    int	   y;
} something_t;

int main(const int argc, const char ** argv) {
    something_t *something;

    something  = PR_Malloc(sizeof(*something));
    something->x = 0;
    something->y = 1;


    return 0;

The functions PR_Calloc and PR_Realloc work as their Posix counterparts. Memory allocated with PR_Malloc, PR_Calloc, PR_Realloc must be freed with PR_Free

String operations

file: strings.c

#include <plstr.h>

int main(const int argc, const char ** argv) {

    const char * str;

    str = PL_strdup("nsrp");


    return 0;

Memory alloctated with PL_strdup, must be freed with PL_Free. The functions PL_strcpy, PL_strlen, work as the posix counter parts.

Dynamic library loading

file: dynamic.c

#include <stdio.h>
#include <prerror.h>
#include <prlink.h>

typedef int (*entry_fnt) (int i);

int main(const int argc, const char ** argv) {
    const char * name = "libsomething.so";
    const char * entry_name = "entry";
    entry_fnt fn;
    int i, j;

    PRLibrary* lib;
    lib = PR_LoadLibrary(name);
    if (lib == NULL) {
        PRErrorCode error_code;

        error_code  = PR_GetError();
        fprintf(stderr, "Error %d\n", error_code);
        return 1;

    j = 0;
    fn = (entry_fnt) PR_FindSymbol(lib, entry_name);
    i = fn(j);


    return 0;

During the linking process the -ldl must be added

Further reading:

We only tipped the top of the iceberg here. There is much more:

  • threadpools, treading, monitors, mutexes, atomic operations
  • processes
  • io with file, mmmap-files and directory access
  • io with networking, sockets and layers
  • interval timers, date and time functions
  • floating point to string conversion
  • log functions
  • shared memory and IPC
  • doublylinked list and hashtables
  • nifty types for pointer arithmetic and calling conventions