Bird
Raised Fist0
Denoframework~20 mins

FFI (Foreign Function Interface) for native code in Deno - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Deno FFI Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ component_behavior
intermediate
2:00remaining
What does this Deno FFI code output?
Consider this Deno FFI snippet that calls a native C function to add two numbers. What will be printed?
Deno
const dylib = Deno.dlopen("./libadd.so", {
  add: { parameters: ["i32", "i32"], result: "i32" }
});

const result = dylib.symbols.add(5, 7);
console.log(result);
dylib.close();
A57
B12
Cundefined
DThrows a runtime error
Attempts:
2 left
💡 Hint
Think about what the native function 'add' is expected to do with two integers.
📝 Syntax
intermediate
2:00remaining
Which option correctly defines a Deno FFI function signature for a C function returning a double?
You want to call a native C function that returns a double and takes a single float parameter. Which Deno FFI signature is correct?
A{ parameters: ["f32"], result: "f64" }
B{ parameters: ["float"], result: "double" }
C{ parameters: ["double"], result: "float" }
D{ parameters: ["f64"], result: "f32" }
Attempts:
2 left
💡 Hint
Deno FFI uses specific type strings like 'f32' and 'f64' for floats and doubles.
🔧 Debug
advanced
2:00remaining
Why does this Deno FFI call throw a TypeError?
Given this code snippet, why does calling dylib.symbols.multiply(3, '4') throw a TypeError?
Deno
const dylib = Deno.dlopen("./libmath.so", {
  multiply: { parameters: ["i32", "i32"], result: "i32" }
});

const result = dylib.symbols.multiply(3, '4');
console.log(result);
dylib.close();
ABecause the second argument is a string, not an integer as required
BBecause the native function multiply is not exported correctly
CBecause the dylib.close() is called before the function call
DBecause the parameters array is missing a third argument type
Attempts:
2 left
💡 Hint
Check the types of arguments passed versus the expected parameter types.
🧠 Conceptual
advanced
2:00remaining
What is the purpose of the 'unsafe' keyword in Deno FFI function definitions?
In Deno FFI, some function definitions include the 'unsafe' flag. What does this flag indicate?
AThe function runs asynchronously and returns a Promise
BThe function is deprecated and should not be used
CThe function may cause undefined behavior if called incorrectly and bypasses some safety checks
DThe function is only available on Windows platforms
Attempts:
2 left
💡 Hint
Consider what 'unsafe' usually means in programming contexts related to memory and calls.
❓ state_output
expert
3:00remaining
What is the value of 'result' after this Deno FFI call sequence?
Given this code, what is the final value of 'result'?
Deno
const dylib = Deno.dlopen("./libcounter.so", {
  increment: { parameters: ["pointer"], result: "void" },
  getValue: { parameters: ["pointer"], result: "i32" }
});

const counter = new Uint32Array(1);
counter[0] = 0;
const ptr = Deno.UnsafePointer.of(counter.buffer);

dylib.symbols.increment(ptr);
dylib.symbols.increment(ptr);
const result = dylib.symbols.getValue(ptr);
dylib.close();
AThrows a TypeError
B0
Cundefined
D2
Attempts:
2 left
💡 Hint
The native 'increment' function increases the value pointed to by the pointer by 1 each call.

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

  1. 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.
  2. Step 2: Compare with other options

    Options B, C, and D relate to other Deno features but not FFI or native code loading.
  3. Final Answer:

    To load a native shared library and access its functions -> Option A
  4. 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

  1. 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".
  2. 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.
  3. Final Answer:

    { myFunc: { parameters: ["i32"], result: "i32" } } -> Option B
  4. Quick Check:

    Integer parameter and return = C [OK]
Hint: Match parameter and result types exactly as strings [OK]
Common Mistakes:
  • Using 'void' as a parameter type incorrectly
  • Mixing return and parameter types
  • Using unsupported types like 'string' without proper handling
3. Given the following code snippet, what will be the output?
const lib = Deno.dlopen("./libmath.so", {
  add: { parameters: ["i32", "i32"], result: "i32" }
});

const result = lib.symbols.add(10, 5);
console.log(result);
lib.close();
medium
A. undefined
B. 105
C. 15
D. Runtime error

Solution

  1. Step 1: Understand the function signature and call

    The native function 'add' takes two 32-bit integers and returns a 32-bit integer. Calling add(10, 5) should return 15.
  2. Step 2: Analyze the output

    The console.log prints the returned value, which is 15. No errors occur because the signature matches and the library is closed properly.
  3. Final Answer:

    15 -> Option C
  4. Quick Check:

    Adding 10 + 5 = 15 [OK]
Hint: Check parameter types and expected return for output [OK]
Common Mistakes:
  • Concatenating numbers as strings (getting 105)
  • Forgetting to close the library
  • Assuming undefined return without checking signature
4. Identify the error in this Deno FFI code snippet:
const lib = Deno.dlopen("./libcalc.so", {
  multiply: { parameters: ["i32", "i32"], result: "i64" }
});

const output = lib.symbols.multiply(3, 4);
console.log(output);
lib.close();
medium
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

  1. 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.
  2. 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.
  3. Final Answer:

    The result type should be "i32" instead of "i64" -> Option A
  4. 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

  1. 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.
  2. 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.
  3. Final Answer:

    Define the function with result type "pointer", then use Deno.UnsafePointerView to read the string -> Option D
  4. 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 unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard