This directory contains examples of embedding the tsrun TypeScript interpreter in C/C++ applications.
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
cd ../.. # Go to project root
cargo build --release --features c-apiThis produces:
target/release/libtsrun.so(Linux)target/release/libtsrun.dylib(macOS)target/release/libtsrun.a(static library)
cd examples/c-embedding
make allmake run-all
# Or individual examples:
make run-basic
make run-native
make run-modules
make run-asyncDemonstrates 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);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)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);
}Demonstrates the order system for async operations:
- Handling
TSRUN_STEP_SUSPENDEDstatus - 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);
}See tsrun.h for the complete API. Key types:
typedef struct {
TsRunValue* value; // NULL on error
const char* error; // NULL on success
} TsRunValueResult;
typedef struct {
bool ok;
const char* error;
} TsRunResult;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;typedef enum {
TSRUN_TYPE_UNDEFINED,
TSRUN_TYPE_NULL,
TSRUN_TYPE_BOOLEAN,
TSRUN_TYPE_NUMBER,
TSRUN_TYPE_STRING,
TSRUN_TYPE_OBJECT,
TSRUN_TYPE_SYMBOL,
} TsRunType;- 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 bytsrun_json_stringify() - Call
tsrun_free_strings()on string arrays fromtsrun_keys()
The library is NOT thread-safe. Use one TsRunContext per thread.
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.