DEV Community

Cover image for Executing C code with JS -- using Node’s exec() function
Siddhant Khare
Siddhant Khare

Posted on • Edited on

Executing C code with JS -- using Node’s exec() function

As I've been delving into the fundamentals of Linux, hardware, and networking, I've grown increasingly fascinated by how programs in various languages are ultimately translated into machine language for execution. This realization sparked my interest in seeing whether I could execute code across different programming paradigms. This led me to successfully run a C program using JavaScript. In this post, I'll explain the process step-by-step, shedding light on both the method and the rationale behind this approach.

1. Preparing the C Program

Let's start with the basics. We need a C program that we intend to run through our JavaScript code. For this demonstration, I chose a simple C program that accepts command-line arguments and prints them. Here's the main.c code:

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

int main (int argc, char *argv[]) {
    for (int i=1; i < argc; i++) {
        printf("%s\n", argv[i]);
    }
    exit(0);
}
Enter fullscreen mode Exit fullscreen mode

This program iterates through given command-line arguments and prints each one on a new line.

2. Compiling the C Program

Before we can run our C code through JavaScript, we need to compile it into an executable. This step transforms the high-level C code into machine code that the computer's processor can execute directly. We use gcc, a popular C compiler:

gcc -o main main.c
Enter fullscreen mode Exit fullscreen mode

Testing it directly in the terminal:

./main hello!
Enter fullscreen mode Exit fullscreen mode

Output:

hello!
Enter fullscreen mode Exit fullscreen mode

3. Crafting the JavaScript Executor

Now for the fun part—creating a JavaScript program that can execute our C program. We'll use Node.js and its child_process module, which allows us to run shell commands directly from JavaScript. This module is part of the Node.js core, so no additional installations are necessary.

Here's main.js:

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

const argValue = 'hello!';  // Sample arguments
const command = `./main ${argValue}`;

exec(command, (error, stdout) => {
    if (error) {
        console.error(`Error: ${error.message}`);
        return;
    }
    console.log(`${stdout}`);
});
Enter fullscreen mode Exit fullscreen mode

4. Putting It All Together

Finally, let's execute the JavaScript program to see if it successfully calls our C executable:

node main.js
Enter fullscreen mode Exit fullscreen mode

Output:

hello!
Enter fullscreen mode Exit fullscreen mode

It works flawlessly! This setup highlights a key concept: compiled languages like C, C++, Go, and Rust convert code into machine language directly, which means their executables can be invoked from scripts written in other languages. However, for interpreted languages like Java and Python, each execution involves the interpreter, which complicates direct calls from scripts in other languages.

Why This Matters

Understanding how different programming languages interact at the system level not only expands our technical repertoire but also enhances our ability to solve complex problems in innovative ways. By harnessing the strengths of both compiled and interpreted languages, we can design systems that are both powerful and flexible.

This exploration is just the tip of the iceberg. The possibilities are vast and varied—ranging from automating system-level tasks to creating complex multi-language architectures. So, let your curiosity lead the way and keep experimenting!


If you're intrigued by the idea of polyglot programming—using multiple programming languages within the same project to leverage each language's strengths—you might find this article on MetaCall helpful: Polyglot Programming with MetaCall. It’s a great resource for those looking to dive deeper into creating versatile, multi-language software solutions. Dive in, and happy coding!


Stay Connected and Get More Insights

If you found this guide helpful and are dealing with similar challenges, don't hesitate to reach out for personalized consulting at Superpeer. For more tech insights and updates, consider following me on GitHub. Let's innovate together!

Top comments (16)

Collapse
 
pcockerell profile image
Peter Cockerell

Am I the only one who thought, from the title of this article, that it was going to be about somehow interpreting a compiled C program from JavaScript in the browser? Admittedly that would be a total waste of time, but at least it would have made the title accurate. The titie of this article should be "Using Node"s exec() function". It has nothing specifically to do with C programs, and barely anything to do with JavaScript as most people would expect, in the context of a browser environment. I doubt that title would have garnered as many clicks, though.

Collapse
 
siddhantkcode profile image
Siddhant Khare

Sorry, that was not the intent. I am changing the title right now as you suggested

Thanks for the feedback <3

Collapse
 
amythical profile image
amythical

I assumed it was something using Emscripten and C.
I have been using Emscripten and will make a post on calling a C program converted to a webassembly using emscripten and called via javascript.

Collapse
 
pcockerell profile image
Peter Cockerell

Now that would be an interesting article! I looked at emscripten, but for my purposes, AssemblyScript was a better choice for writing Wasm functions.

Thread Thread
 
amythical profile image
amythical

Will make one soon, I am working on some emscripten and its been a struggle but it's all worth it when you see pointers exchanged between C and javascript.

Thread Thread
 
amythical profile image
amythical
Collapse
 
pauljlucas profile image
Paul J. Lucas

Agreed. The language the called program is written in is irrelevant. It could be written in any language.

Collapse
 
ezpieco profile image
Ezpie

Just like they said, "if something can be made with JavaScript, it will be made with JavaScript".

Collapse
 
siddhantkcode profile image
Siddhant Khare

haha :D

Collapse
 
kervyntjw profile image
Kervyn

This is cool, I've been looking for a solution to run shell scripts in my EC2 without resorting to changing from JavaScript, thanks for the insight!

Collapse
 
legationpro profile image
Anze

Awesome post! Do you have a solution for executing FFI from C in JavaScript?

Collapse
 
siddhantkcode profile image
Siddhant Khare

Ahh! Good question, i've never tried it. But, found this node-ffi from google search, maybe it will work.

Collapse
 
jim_noord_85b359570083682 profile image
Jim Noord

JavaScript can do some amazing things, though not necessarily quickly. for instance, I once implemented Brenham's line and circle algorithms using JavaScript. Thing to keep in mind is that JavaScript was specifically designed to not be able to be used to access the file system of the client except on Server Side Javascript, and even then, pretty dangerous. When you give shell access to a program, the permissions run at the system level. That means a hacker could gain access to the machine and anything on it, and even use it to access other machines on the network

Collapse
 
eugrus profile image
Info Comment hidden by post author - thread only accessible via permalink
Evgeny Fishgalov

Of course you can invoke a binary from any (system scripting language) script. The amount of filler text before and after, as well as the overly complicated wrap around exec() makes me wonder if it's mostly a ChatGPT generated article. The title "Executing C Code with JavaScript" is extremely misleading.

Collapse
 
bcamphart profile image
Info Comment hidden by post author - thread only accessible via permalink
B. Camphart

My thoughts too. I came in expecting a C compiler or interpreter written in JavaScript.

Collapse
 
neurabot profile image
Neurabot

learnful.

Some comments have been hidden by the post's author - find out more