📖 Scenario: You want to use a simple native C function from your Deno script. This helps when you need fast or system-level code that JavaScript alone can't do easily.
🎯 Goal: Build a Deno script that calls a native C function using FFI (Foreign Function Interface). You will load the native library, define the function signature, and call the function.
📋 What You'll Learn
Create a Deno ForeignLibrary object to load the native library
Define the native function signature with correct parameter and result types
Call the native function from Deno and store the result
Print the result using Deno's console.log
💡 Why This Matters
🌍 Real World
Using FFI lets you run fast native code or access system features not available in JavaScript, useful for performance-critical apps or hardware access.
💼 Career
Many jobs require integrating JavaScript with native code for performance or legacy reasons. Knowing FFI in Deno is valuable for backend and systems programming.
Progress0 / 4 steps
1
Load the native library with Deno's FFI
Create a constant called lib that loads the native library ./libsimple.so using Deno.dlopen with an empty symbols object {}.
Deno
Hint
Use Deno.dlopen with the path and an empty object for symbols first.
2
Define the native function signature
Update the lib constant to load ./libsimple.so with a symbol called add. Define add as a function with parameters i32 and i32 and result i32.
Deno
Hint
Inside the second argument object, add a key add with parameters array and result type.
3
Call the native function and store the result
Create a constant called sum and assign it the result of calling lib.symbols.add(10, 20).
Deno
Hint
Use lib.symbols.add(10, 20) to call the native function.
4
Print the result and close the library
Use console.log to print the value of sum. Then call lib.close() to release the native library resources.
Deno
Hint
Print sum with console.log and then call lib.close().
Practice
(1/5)
1. What is the main purpose of using Deno.dlopen in Deno's FFI?
easy
A. To load a native shared library and access its functions
B. To compile TypeScript code into JavaScript
C. To start a web server in Deno
D. To read files from the filesystem
Solution
Step 1: Understand the role of Deno.dlopen
Deno.dlopen is used to load native shared libraries (like .dll, .so, .dylib) so Deno can call native functions.
Step 2: Compare with other options
Options B, C, and D relate to other Deno features but not FFI or native code loading.
Final Answer:
To load a native shared library and access its functions -> Option A
Quick Check:
Deno.dlopen loads native libraries = A [OK]
Hint: Remember: dlopen means 'dynamic library open' [OK]
Common Mistakes:
Confusing dlopen with file reading functions
Thinking dlopen compiles code
Mixing up server start with FFI loading
2. Which of the following is the correct way to define a function signature for a native function returning an integer in Deno.dlopen?
easy
A. { myFunc: { parameters: ["i32"], result: "void" } }
B. { myFunc: { parameters: ["i32"], result: "i32" } }
C. { myFunc: { parameters: ["void"], result: "i32" } }
D. { myFunc: { parameters: [], result: "string" } }
Solution
Step 1: Understand function signature format
Function signatures in Deno.dlopen require specifying parameter types and the return type. For a function taking an integer and returning an integer, both parameters and result should be "i32".
Step 2: Analyze each option
{ myFunc: { parameters: ["i32"], result: "void" } } returns void, not integer. { myFunc: { parameters: ["void"], result: "i32" } } has parameters as void which is invalid. { myFunc: { parameters: [], result: "string" } } returns string but parameters are empty. Only { myFunc: { parameters: ["i32"], result: "i32" } } correctly matches integer parameter and integer return.
A. The result type should be "i32" instead of "i64"
B. The parameters array should be empty
C. The library path is incorrect
D. The function call syntax is invalid
Solution
Step 1: Check function signature consistency
The function 'multiply' takes two 32-bit integers and likely returns a 32-bit integer. Using "i64" as result type can cause mismatch errors if the native function returns 32-bit.
Step 2: Validate other parts
Parameters are correctly specified as two "i32". The library path and function call syntax are valid assuming the file exists and function is exported.
Final Answer:
The result type should be "i32" instead of "i64" -> Option A
Quick Check:
Result type must match native function = D [OK]
Hint: Match return type exactly with native function signature [OK]
Common Mistakes:
Changing parameter types incorrectly
Assuming library path error without checking
Misusing function call syntax
5. You want to call a native function that returns a pointer to a UTF-8 string. Which approach correctly handles this in Deno FFI?
hard
A. Define the function with result type "string" and use it directly
B. Define the function with result type "i32" and convert to string
C. Define the function with result type "void" and cast the result to string
D. Define the function with result type "pointer", then use Deno.UnsafePointerView to read the string
Solution
Step 1: Understand pointer return handling
Native functions returning strings usually return pointers. Deno FFI requires defining the result as "pointer" to get the address.
Step 2: Use Deno.UnsafePointerView to read UTF-8
After getting the pointer, Deno.UnsafePointerView can read the memory as a UTF-8 string safely.
Final Answer:
Define the function with result type "pointer", then use Deno.UnsafePointerView to read the string -> Option D
Quick Check:
Pointer + UnsafePointerView for strings = B [OK]
Hint: Use pointer type and UnsafePointerView for native strings [OK]
Common Mistakes:
Using 'string' as result type directly
Casting void or integer to string incorrectly
Ignoring memory safety when reading pointers
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.