DEV Community

Cover image for How can I bind OLSRT to Node.js?
Javad
Javad

Posted on

How can I bind OLSRT to Node.js?

Hey Dev Community!
I'm glad to share a new post with you!
I've been working on OLSRT, a lightweight runtime written in pure C.
It brings together concepts like Actors, Channels, Promise/Futures, Event Loop, WebSocket, HTTP, Parallel, and Poller into one modular system.

Think of it as a flexible foundation for building event-driven applications, similar in spirit to Node.js or libuv, but desgined to be minimal and hackable, but powerful.

Here's a tiny example of how a promise & future works in OLSRT (C++):

#include "olsrt.h"
#include <iostream>
#include <string>
#include <vector>

// Callback for future
void print_callback(ol_future_t* f, void* arg) {
    const char* msg = static_cast<const char*>(arg);
    std::cout << msg << std::endl;
}

int main() {
    // Making a loop
    ol_loop_t* loop = ol_loop_create();

    // Making future
    ol_future_t* f = ol_future_create(loop);

    // Some callbacks...
    ol_future_then(f, print_callback, (void*)"Async Message");
    ol_future_then(f, print_callback, (void*)"Another Async Message");
    ol_future_then(f, print_callback, (void*)"Yet another one");
    ol_future_then(f, print_callback, (void*)"Finished async chain");

    // Just a simply hello world
    std::cout << "Hello, World!" << std::endl;

    // Resolve future -> Running all callbacks
    ol_future_resolve(f, nullptr);

    // Running loop (For Async Dispatch)
    ol_loop_run(loop);

    // Cleanup the memory
    ol_loop_destroy(loop);
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

For binding to node.js, first you must install N-API or node-addon-api, here is an example with node-addon-api:
Project structure:

olsrt-node/
-|- binding.gyp // Settings
-|- index.js // Our node.js example
-|- core/
     -|- promise.cpp // Binding
-|- OLSRT/ // OverLab Streams Runtime Core & Includes
     -|- src/
         -|- actors.c
         -|- ...
     -|- includes
         -|- compat.h
         -|- olsrt.h
Enter fullscreen mode Exit fullscreen mode

Example of binding.gyp file:

{
    "targets": [
        {
            "target_name": "olsrt",
            "sources": [ "core/promise.cpp" ],
            "include_dirs": [
                "<!(node -p \"require('node-addon-api').include\")",
                "../OLSRT/include"
            ],
            "dependencies": [
                "<!(node -p \"require('node-addon-api').gyp\")"
            ],
            "cflags": [ "-fno-exceptions" ],
            "cflags_CC!": [ "-fno-exceptions" ],
            "defines": [ "NAPI_DISABLE_CPP_EXCEPTIONS" ]
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

core/promise.cpp (Binding):

#include "napi.h"
#include "olsrt.h"
#include <string>
#include <iostream>

struct FutureWrapper {
    ol_future_t* future;
};

Napi::Value CreateFuture(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    ol_loop_t* loop = ol_loop_create();
    FutureWrapper* fw = new FutureWrapper();
    fw->future = ol_future_create(loop);
    return Napi::External<FutureWrapper>::New(env, fw);
}

Napi::Value ResolveFuture(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    auto fw = info[0].As<Napi::External<FutureWrapper>>().Data();
    ol_future_resolve(fw->future, nullptr);
    return env.Undefined();
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
    exports.Set("createFuture", Napi::Function::New(env, CreateFuture));
    exports.Set("resolveFuture", Napi::Function::New(env, ResolveFuture));
    return exports;
}

NODE_API_MODULE(olsrt, Init);
Enter fullscreen mode Exit fullscreen mode

Then, you must install and build:

npm install node-addon-api
node-gyp configure build
Enter fullscreen mode Exit fullscreen mode

An example in Node.js (index.js):

const olsrt = require('./build/Release/olsrt');

// Making Future
const f = olsrt.createFuture();

// Emulating Promise in JS
function wrapFuture(f) {
  return new Promise((resolve) => {
    // In full version (e.g Production), we must define ol_future_then
    // Here, we have call resolveFuture by our hands, future_then will do it automatially
    setTimeout(() => {
      olsrt.resolveFuture(f);
      resolve();
    }, 100);
  });
}

console.log("Hello World");

wrapFuture(f).then(() => {
  console.log("Async message");
  console.log("Another async message");
  console.log("Yet another one");
  console.log("Finished async chain");
});
Enter fullscreen mode Exit fullscreen mode

The output must something like this:

Async message
Another async message
Yet another one
Finished async chain
Enter fullscreen mode Exit fullscreen mode

This was just one of the smallest things that OLSRT can do! Imagine what it can do in Enterprise-grade projects!

But in this post, we want you to discuss with each other, I'd love to hear your thoughts:

  • Which features would you like to see next?
  • Would node.js bindings be useful for your projects?
  • How do you imagine using OLSRT in your own projects?

If anything was wrong, sorry for that.

I will see all of you in the next posts! Have a nice OLSRT day :)

Top comments (0)