-
Notifications
You must be signed in to change notification settings - Fork 10
Importing libc in typescript
Let's write a simple program in typescript to take input from the user and greet, using only native C functions from libc.
-
Create a new project with
bun init
. -
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.
-
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. -
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")); }
-
Now let's allocate memory where we'll store the user input.
const name = Buffer.alloc(50);
-
Print the message asking the user to input their name.
printf(cstr("Enter your name: "));
-
Get the input from the user and store that in the buffer allocated earlier by passing the pointer of it.
gets(ptr(name));
-
Now, print the message to greet the user.
printf(cstr(`Hello, ${name}`));
-
Exit the program with an exit code
0
.exit(0);
-
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);
-
That's it. Now run
bun .
to run index.ts. -
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.
-
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 }, }
-
We are done. Run
bun .
again to rerun the script. -
Enter your name and press enter.
-
The program works as expected. Entirely through native libc functions and not any javascript functions (excluding the code to convert strings and allocation).