C++ / JSX Interop
Import user C++ functions directly into your JSX code. No FFI, no bindings — the C++ is compiled into the same binary.
Basic Usage
Create a .cpp file and import its functions:
// src/App.mx
import { doubleIt, area } from './native.cpp'// src/native.cpp
int doubleIt(int x) {
return x * 2;
}
double area(double w, double h) {
return w * h;
}Use the imported functions in event handlers:
<button onClick={() => setCount(doubleIt(count))}>Double it</button>
<button onClick={() => setArea(area(5, 7))}>Compute area</button>How It Works
- Morph detects
import { fn } from './file.cpp'in your.mxfile - The user
.cppfile is#includedinto the generated translation unit - Functions are callable directly from JSX event handlers
- A
_morph_state.hheader is generated exposing signals and setter wrappers so C++ can update state and call JSX code
C++ → JSX State
C++ code can update morphState signals from any thread:
#include "morph_api.h"
void loadData() {
setStatus("loading...");
std::thread([]() {
// ... do work ...
setData("result");
setStatus("done");
}).detach();
}The setStatus() and setData() functions are generated wrappers that update the corresponding morphState signals. They are mutex-protected and safe to call from worker threads.
C++ → JSX Function Calls
C++ can call functions defined in your JSX:
// src/App.mx
function jsxHelper(x: int): int {
return x * 10 + 1
}// C++ can call jsxHelper via the generated header
#include "_morph_state.h"
int callJsxFromCpp(int x) {
return jsxHelper(x);
}Configuration
Set build options for your C++ imports in morph.config.json:
{
"native": {
"include_dirs": ["libs/include"],
"library_dirs": ["libs/lib"],
"libraries": ["png", "z"],
"cflags": ["-O3"],
"ldflags": []
}
}See Configuration for all options.
Example
import { CSS, morphState } from 'morph'
import { doubleIt, area, runAsync } from './native.cpp'
CSS.load("style.css")
export const windowConfig = { title: "Interop", width: 640, height: 400 }
export default function App() {
const [count, setCount] = morphState(0)
const [status, setStatus] = morphState("idle")
return (
<body>
<div>Count: {count}</div>
<button onClick={() => setCount(doubleIt(count))}>Double it</button>
<button onClick={() => runAsync(count)}>Run async</button>
<div>{status}</div>
</body>
)
}See the native-interop test for a complete working example.