Skip to content

Latest commit

 

History

History

README.md

C Embedding Examples

This directory contains examples of embedding the tsrun TypeScript interpreter in C/C++ applications.

Overview

tsrun provides a C API that allows you to:

  • Evaluate TypeScript/JavaScript code
  • Inspect and manipulate values
  • Register native C functions callable from JS
  • Handle ES module imports
  • Process async operations via the order system

Building

1. Build the Rust library with C API support

cd ../..  # Go to project root
cargo build --release --features c-api

This produces:

  • target/release/libtsrun.so (Linux)
  • target/release/libtsrun.dylib (macOS)
  • target/release/libtsrun.a (static library)

2. Build the examples

cd examples/c-embedding
make all

3. Run the examples

make run-all
# Or individual examples:
make run-basic
make run-native
make run-modules
make run-async

Examples

basic.c - Basic Usage

Demonstrates fundamental operations:

  • Creating and freeing interpreter contexts
  • Evaluating expressions
  • Inspecting return values (type checking, extracting primitives)
  • Working with objects and arrays
  • JSON serialization
TsRunContext* ctx = tsrun_new();

TsRunResult prep = tsrun_prepare(ctx, "1 + 2 * 3", NULL);
TsRunStepResult result;
tsrun_run(&result, ctx);

if (result.status == TSRUN_STEP_COMPLETE) {
    printf("Result: %f\n", tsrun_get_number(result.value));
    tsrun_value_free(result.value);
}

tsrun_step_result_free(&result);
tsrun_free(ctx);

native_functions.c - Native Functions

Demonstrates registering C functions that can be called from JavaScript:

  • Simple functions (add, greet)
  • Functions returning objects
  • Stateful functions using userdata
  • Functions that call back into JS
static TsRunValue* native_add(TsRunContext* ctx, TsRunValue* this_arg,
                              TsRunValue** args, size_t argc,
                              void* userdata, const char** error_out) {
    double a = tsrun_get_number(args[0]);
    double b = tsrun_get_number(args[1]);
    return tsrun_number(ctx, a + b);
}

// Register and use
TsRunValueResult fn = tsrun_native_function(ctx, "add", native_add, 2, NULL);
tsrun_set_global(ctx, "add", fn.value);
// Now callable from JS: add(10, 20)

module_loading.c - Module System

Demonstrates handling ES module imports:

  • Step-based execution with TSRUN_STEP_NEED_IMPORTS
  • Providing module source code
  • Accessing module exports from C
TsRunStepResult result;
tsrun_run(&result, ctx);

while (result.status == TSRUN_STEP_NEED_IMPORTS) {
    for (size_t i = 0; i < result.import_count; i++) {
        const char* path = result.imports[i].resolved_path;
        const char* source = load_file(path);
        tsrun_provide_module(ctx, path, source);
    }
    tsrun_step_result_free(&result);
    tsrun_run(&result, ctx);
}

async_orders.c - Async Operations

Demonstrates the order system for async operations:

  • Handling TSRUN_STEP_SUSPENDED status
  • Processing orders (requests from JS)
  • Fulfilling orders with responses
  • Handling cancellation
while (result.status == TSRUN_STEP_SUSPENDED) {
    for (size_t i = 0; i < result.pending_count; i++) {
        TsRunOrder* order = &result.pending_orders[i];
        // Examine order->payload to determine what to do
        // Create response...
    }
    tsrun_fulfill_orders(ctx, responses, count);
    tsrun_step_result_free(&result);
    tsrun_run(&result, ctx);
}

API Reference

See tsrun.h for the complete API. Key types:

Result Types

typedef struct {
    TsRunValue* value;    // NULL on error
    const char* error;    // NULL on success
} TsRunValueResult;

typedef struct {
    bool ok;
    const char* error;
} TsRunResult;

Step Status

typedef enum {
    TSRUN_STEP_CONTINUE,     // More to execute
    TSRUN_STEP_COMPLETE,     // Finished with value
    TSRUN_STEP_NEED_IMPORTS, // Waiting for modules
    TSRUN_STEP_SUSPENDED,    // Waiting for order fulfillment
    TSRUN_STEP_DONE,         // No active execution
    TSRUN_STEP_ERROR,        // Execution error
} TsRunStepStatus;

Value Types

typedef enum {
    TSRUN_TYPE_UNDEFINED,
    TSRUN_TYPE_NULL,
    TSRUN_TYPE_BOOLEAN,
    TSRUN_TYPE_NUMBER,
    TSRUN_TYPE_STRING,
    TSRUN_TYPE_OBJECT,
    TSRUN_TYPE_SYMBOL,
} TsRunType;

Memory Management

  • Call tsrun_value_free() on all values when done
  • Call tsrun_step_result_free() on step results (but NOT before freeing the value)
  • Call tsrun_free_string() on strings returned by tsrun_json_stringify()
  • Call tsrun_free_strings() on string arrays from tsrun_keys()

Thread Safety

The library is NOT thread-safe. Use one TsRunContext per thread.

Error Handling

All fallible operations return result structs. Check the error field or ok status:

TsRunValueResult result = tsrun_json_parse(ctx, invalid_json);
if (!result.value) {
    printf("Error: %s\n", result.error);
}

Error strings are valid until the next tsrun_* call on the same context.