Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call C function from nodeJS

Tags:

c

node.js

I have some C functions that I need to call frequently from nodeJS (less than 1 second time intervals). The C function takes in an argument and returns a value, which might be an int or an array.

It can be as simple as below:

int main() {
    int x = 2;
    return x;
}

And I need to get the value x in nodeJS and be able to do console.log(x)

I tried using node-ffi, but I read from the internet that it has a large overhead and is thus inefficient for frequent function calls.

I also considered writing addons but it seems very troublesome (with unfamiliar V8, C++ code and all that...)

And there is not much resources regarding integration between nodeJS and C (they are mostly nodeJS with C++)

Could somebody help shed some light on this? Thanks.

like image 998
ccying Avatar asked Jul 23 '17 14:07

ccying


People also ask

Can you run C code in JavaScript?

js can dynamically load an external C or C++ DLL file at runtime and utilize its API to perform some operations written inside it from a JavaScript program. This is basically how a Native Addon works in Node.

How do I call a node JS function in C++?

js Addons are dynamically-linked shared objects, written in C++, that can be loaded into Node. js using the require() function, and used just as if they were an ordinary Node. js module. They are used primarily to provide an interface between JavaScript running in Node.

What is FFI Napi?

js Foreign Function Interface for N-API. node-ffi-napi is a Node. js addon for loading and calling dynamic libraries using pure JavaScript. It can be used to create bindings to native libraries without writing any C++ code. It also simplifies the augmentation of node.

What is Libuv and how does node js use it?

libuv: libuv is a C library originally written for Node. js to abstract non-blocking I/O operations. Event-driven asynchronous I/O model is integrated. It allows the CPU and other resources to be used simultaneously while still performing I/O operations, thereby resulting in efficient use of resources and network.


1 Answers

change your c code to

// myProgram.c
#include <stdio.h>
int main(void){
    puts("4");
    return 0;
}

compile it with gcc, in the same directory as your node file

$ gcc -o myProgram myProgram.c

in your node file, require exec()

const { exec } = require("child_process");

and use it like so:

exec("./myProgram", (error, stdout, stderr) => console.log(stdout));

This works well, it spins up a new process every time.

If, on the other hand, you want to keep the child process running, and call a function in that code from node, you can do that like this:

// multiplyBy2.c

#include <stdio.h>
#include <stdlib.h>

int timesTwo(int x){
    return x*2;
}

int main(void){
  char buff[100];
  int input,output;
  while(1){
    gets(buff);
    input = atoi(buff);
    output = timesTwo(input);
    printf("%d", output);
    // you must flush stdout or else node will hang!
    fflush(stdout);
  }
  return 0;
}

compile multiplyBy2.c and then:

// myNodeApp.js

const {spawn} = require('child_process');
const __delay__ = t => new Promise(resolve=>setTimeout(()=>resolve(), t))
const ch = spawn('./multiplyBy2')

var result=undefined;

ch.stdout.on("data",(data)=>{
    result = parseInt(data.toString())
})

async function multiplyBy2InC(num){
    ch.stdin.write(`${num}\n`)
    while(result==undefined)
      await __delay__(1)
    const output = result
    result = undefined
    return output
}

// now you could call it like this, it will print 20 to the console
multiplyBy2InC(10).then(r=>console.log(r))


like image 77
Marchingband Avatar answered Oct 02 '22 01:10

Marchingband