| CARVIEW |
Select Language
HTTP/2 200
date: Mon, 29 Dec 2025 09:22:49 GMT
content-type: text/html; charset=utf-8
vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With,Accept-Encoding, Accept, X-Requested-With
x-robots-tag: none
etag: W/"37b8d86dd610a697c297c39de07e5b61"
cache-control: max-age=0, private, must-revalidate
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: no-referrer-when-downgrade
content-security-policy: default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com github.githubassets.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com wss://alive-staging.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com marketplace-screenshots.githubusercontent.com/ copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com github.githubassets.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/
server: github.com
content-encoding: gzip
accept-ranges: bytes
set-cookie: _gh_sess=Fin2O1DIgb4uX739cqEgbNFt6ijem5wlXQ%2B2fBea%2FuxnIPyIjmkOhSq1LlzmujP924gnnFTZZdJh0195Exu4vB%2FUEhET0vbEEwd27EDp5GtVLOzpnhtbyQYGKOOwVSwluiwsE3g9aAvllLLpXkLrot24vj50dOeQtSrtOtNWM%2FeX7bAREHO0yuM62r03Uluk2h9de4DFjEQakMrx8Nh%2B1n%2FOil0F1sHb0G0zMcORN0wpYb7rusu9Zpgx6FoUnT%2FxrslgEncuai3p0OnGeNVnOw%3D%3D--sJF0JtodX4woGuNY--o9CVhEiH8%2FnxyAqLytY8BA%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax
set-cookie: _octo=GH1.1.1522224401.1767000168; Path=/; Domain=github.com; Expires=Tue, 29 Dec 2026 09:22:48 GMT; Secure; SameSite=Lax
set-cookie: logged_in=no; Path=/; Domain=github.com; Expires=Tue, 29 Dec 2026 09:22:48 GMT; HttpOnly; Secure; SameSite=Lax
x-github-request-id: B3D4:292CC8:5D38AC3:7043D79:69524868
Using the C API with JavaScript · cartesi/machine-emulator Wiki · GitHub
Skip to content
Navigation Menu
{{ message }}
-
Notifications
You must be signed in to change notification settings - Fork 42
Using the C API with JavaScript
Eduardo Bart edited this page Jan 23, 2025
·
5 revisions
Before trying this example first make sure:
- You have Cartesi Machine installed globally in your system.
- You have
linux.binandrootfs.ext2images available locally (you could copy them from your installation). - You have a Node 20.x+ installed.
- You are using Cartesi Machine 0.19+ (contains the new C API, it's not released yet).
We will be binding using koffi C FFI module for Node. You can install it with:
npm install koffiFirst make sure you have koffi package installed.
The following example boots a machine and prints a hello message:
// Bindings
const koffi = require('koffi')
const cartesi = koffi.load('libcartesi.so')
const CM_ERROR_OK = 0
const CM_MCYCLE_MAX = 0xffffffffffffffffff
const CM_BREAK_REASON_FAILED = 0
const CM_BREAK_REASON_HALTED = 1
const CM_BREAK_REASON_YIELDED_MANUALLY = 2
const CM_BREAK_REASON_YIELDED_AUTOMATICALLY = 3
const CM_BREAK_REASON_YIELDED_SOFTLY = 4
const CM_BREAK_REASON_REACHED_TARGET_MCYCLE = 5
const CM_REG_MCYCLE = 69
const cm_machine = koffi.opaque('cm_machine')
const cm_break_reason = koffi.alias('cm_break_reason', 'int32_t')
const cm_get_last_error_message = cartesi.func('const char *cm_get_last_error_message()')
const cm_create_new = cartesi.func('int32_t cm_create_new(const char *config, const char *runtime_config, _Out_ cm_machine **new_machine)')
const cm_delete = cartesi.func('void cm_delete(cm_machine *m)')
const cm_run = cartesi.func('int32_t cm_run(cm_machine *m, uint64_t mcycle_end, _Out_ cm_break_reason *break_reason)')
const cm_read_reg = cartesi.func('int32_t cm_read_reg(const cm_machine *m, int32_t reg, _Out_ uint64_t *val)')
// Set machine configuration
const config = {
dtb: {
entrypoint: "echo Hello from inside!",
},
flash_drive: [
{image_filename: "rootfs.ext2"},
],
ram: {
image_filename: "linux.bin",
length: 0x8000000,
},
}
const runtime_config = {}
// Create a new machine
let machine_out = [null]
if (cm_create_new(JSON.stringify(config), JSON.stringify(runtime_config), machine_out) != CM_ERROR_OK) {
throw new Error(`failed to create machine: ${cm_get_last_error_message()}`)
}
let machine = machine_out[0]
// Wrap in a try/finally block to auto free machine memory
try {
// Run the machine
let break_reason_out = [null]
if (cm_run(machine, CM_MCYCLE_MAX, break_reason_out) != CM_ERROR_OK) {
throw new Error(`failed to run machine: ${cm_get_last_error_message()}`)
}
let break_reason = break_reason_out[0]
// Print reason for run interruption
switch (break_reason) {
case CM_BREAK_REASON_HALTED:
console.log("Halted")
break
case CM_BREAK_REASON_YIELDED_MANUALLY:
console.log("Yielded manually")
break
case CM_BREAK_REASON_YIELDED_AUTOMATICALLY:
console.log("Yielded automatically")
break
case CM_BREAK_REASON_YIELDED_SOFTLY:
console.log("Yielded softly")
break
case CM_BREAK_REASON_REACHED_TARGET_MCYCLE:
console.log("Reached target machine cycle")
break
case CM_BREAK_REASON_FAILED:
default:
console.log("Interpreter failed")
break
}
// Read and print machine cycles
let mcycle_out = [null]
if (cm_read_reg(machine, CM_REG_MCYCLE, mcycle_out) != CM_ERROR_OK) {
throw new Error(`failed to read machine cycle: ${cm_get_last_error_message()}`)
}
let mcycle = mcycle_out[0]
console.log("Cycles:", mcycle)
} finally {
cm_delete(machine)
}Compile and run with:
node example.jsYou should get the following output:
Hello from inside!
Halted
Cycles: 48985837
To perform input/output operations from inside a machine to the outside you can use the CMIO (Cartesi Machine IO) with its GIO (generic IO) interface, the following example demonstrates this:
// Bindings
const koffi = require('koffi')
const cartesi = koffi.load('libcartesi.so')
const CM_ERROR_OK = 0
const CM_MCYCLE_MAX = 0xffffffffffffffffff
const CM_CMIO_YIELD_COMMAND_MANUAL = 1
const CM_BREAK_REASON_FAILED = 0
const CM_BREAK_REASON_HALTED = 1
const CM_BREAK_REASON_YIELDED_MANUALLY = 2
const CM_BREAK_REASON_YIELDED_AUTOMATICALLY = 3
const CM_BREAK_REASON_YIELDED_SOFTLY = 4
const CM_BREAK_REASON_REACHED_TARGET_MCYCLE = 5
const CM_REG_MCYCLE = 69
const cm_machine = koffi.opaque('cm_machine')
const cm_break_reason = koffi.alias('cm_break_reason', 'int32_t')
const cm_get_last_error_message = cartesi.func('const char *cm_get_last_error_message()')
const cm_create_new = cartesi.func('int32_t cm_create_new(const char *config, const char *runtime_config, _Out_ cm_machine **new_machine)')
const cm_delete = cartesi.func('void cm_delete(cm_machine *m)')
const cm_run = cartesi.func('int32_t cm_run(cm_machine *m, uint64_t mcycle_end, _Out_ cm_break_reason *break_reason)')
const cm_read_reg = cartesi.func('int32_t cm_read_reg(const cm_machine *m, int32_t reg, _Out_ uint64_t *val)')
const cm_receive_cmio_request = cartesi.func('int32_t cm_receive_cmio_request(const cm_machine *m, _Out_ uint8_t *cmd, _Out_ uint16_t *reason, uint8_t *data, _Inout_ uint64_t *length)')
const cm_send_cmio_response = cartesi.func('int32_t cm_send_cmio_response(cm_machine *m, uint16_t reason, const uint8_t *data, uint64_t length)')
// Set machine configuration
const config = {
dtb: {
entrypoint: `echo '{"domain":16,"id":"'$(echo -n Hello from inside! | hex --encode)'"}' | rollup gio | grep -Eo '0x[0-9a-f]+' | tr -d '\n' | hex --decode; echo`,
},
flash_drive: [
{image_filename: "rootfs.ext2"},
],
ram: {
image_filename: "linux.bin",
length: 0x8000000,
},
}
const runtime_config = {}
// Create a new machine
let machine_out = [null]
if (cm_create_new(JSON.stringify(config), JSON.stringify(runtime_config), machine_out) != CM_ERROR_OK) {
throw new Error(`failed to create machine: ${cm_get_last_error_message()}`)
}
let machine = machine_out[0]
// Wrap in a try/finally block to auto free machine memory
try {
// Run the machine
if (cm_run(machine, CM_MCYCLE_MAX, null) != CM_ERROR_OK) {
throw new Error(`failed to run machine: ${cm_get_last_error_message()}`)
}
// Receive GIO request
let cmd_out = [null], domain_out = [null];
let request_data = Buffer.alloc(1024);
let length_out = [request_data.length];
if (cm_receive_cmio_request(machine, cmd_out, domain_out, request_data, length_out) != CM_ERROR_OK) {
throw new Error(`failed to receive CMIO request: ${cm_get_last_error_message()}`)
}
let cmd = cmd_out[0], domain = domain_out[0];
if (cmd != CM_CMIO_YIELD_COMMAND_MANUAL || domain != 16) {
throw new Error("unsupported CMIO request, expected GIO with domain=16")
}
let length = length_out[0];
console.log(request_data.toString('utf8', 0, length));
// Send GIO response
let response_data = Buffer.from("Hello from outside!", 'utf8')
if (cm_send_cmio_response(machine, domain, response_data, response_data.length) != CM_ERROR_OK) {
throw new Error("failed to send CMIO response")
}
// Resume the machine
let break_reason_out = [null]
if (cm_run(machine, CM_MCYCLE_MAX, break_reason_out) != CM_ERROR_OK) {
throw new Error(`failed to resume machine: ${cm_get_last_error_message()}`)
}
let break_reason = break_reason_out[0]
// Print reason for run interruption
switch (break_reason) {
case CM_BREAK_REASON_HALTED:
console.log("Halted")
break
case CM_BREAK_REASON_YIELDED_MANUALLY:
console.log("Yielded manually")
break
case CM_BREAK_REASON_YIELDED_AUTOMATICALLY:
console.log("Yielded automatically")
break
case CM_BREAK_REASON_YIELDED_SOFTLY:
console.log("Yielded softly")
break
case CM_BREAK_REASON_REACHED_TARGET_MCYCLE:
console.log("Reached target machine cycle")
break
case CM_BREAK_REASON_FAILED:
default:
console.log("Interpreter failed")
break
}
// Read and print machine cycles
let mcycle_out = [null]
if (cm_read_reg(machine, CM_REG_MCYCLE, mcycle_out) != CM_ERROR_OK) {
throw new Error(`failed to read machine cycle: ${cm_get_last_error_message()}`)
}
let mcycle = mcycle_out[0]
console.log("Cycles:", mcycle)
} finally {
cm_delete(machine)
}Compile and run with:
node example-gio.jsYou should get the following output:
Hello from inside!
Hello from outside!
Halted
Cycles: 61800308
For more information on how to use API please read the C API header, every function there is documented.
Clone this wiki locally
You can’t perform that action at this time.