Skip to content

Importing libc in typescript

Aritra Karak edited this page Oct 14, 2023 · 2 revisions

Let's write a simple program in typescript to take input from the user and greet, using only native C functions from libc.

  1. Create a new project with bun init.

  2. Copy libc.so.6 into your project directory.

    cp /lib64/libc.so.6 libc.so

    We're renaming it because importing files ending with a number in the extension doesn't work yet. See here.

  3. Inside index.ts, import these functions.

    import { printf, gets, exit } from "./libc.so";
    import { ptr } from "bun:ffi";

    You'll see the typescript error Cannot find module when importing from libc.so, don't worry, it gets fixed in the next steps.

  4. Let's define a function to convert a JS string to a C string. Learn why.

    export function cstr(value: string) {
        return ptr(new TextEncoder().encode(value + "\0"));
    }
  5. Now let's allocate memory where we'll store the user input.

    const name = Buffer.alloc(50);
  6. Print the message asking the user to input their name.

    printf(cstr("Enter your name: "));
  7. Get the input from the user and store that in the buffer allocated earlier by passing the pointer of it.

    gets(ptr(name));
  8. Now, print the message to greet the user.

    printf(cstr(`Hello, ${name}`));
  9. Exit the program with an exit code 0.

    exit(0);
  10. Your index.ts should now look like this.

    import { printf, gets, exit } from "./libc.so";
    import { ptr } from "bun:ffi";
    
    export function cstr(value: string) {
        return ptr(new TextEncoder().encode(value + "\0"));
    }
    
    const name = Buffer.alloc(50);
    
    printf(cstr("Enter your name: "));
    gets(ptr(name));
    
    printf(cstr(`Hello, ${name}`));
    
    exit(0);
  11. That's it. Now run bun . to run index.ts.

  12. You'll see this in your console saying the config file has been generated.

    [HYPERIMPORT]: Library Loader
    No configuration was found for "/hypertest/libc.so"
    
    Config file has been generated at "/hypertest/@types/libc.so/config.ts"
    Edit the config.ts and set the argument and return types, then rerun the script.
    
  13. Open the config.ts file and add the symbol definitions for the functions we imported earlier.

    symbols: {
        printf: {
            args: [T.cstring],
            returns: T.void
        },
        gets: {
            args: [T.pointer],
            returns: T.void
        },
        exit: {
            args: [T.int],
            returns: T.void
        },
    }
  14. We are done. Run bun . again to rerun the script.

  15. Enter your name and press enter.

  16. The program works as expected. Entirely through native libc functions and not any javascript functions (excluding the code to convert strings and allocation).

Clone this wiki locally