18 · Modules
C and C++ with extern
Native functions, C++ objects and vcpkg packages with the native provider.
On this page
Import the language from the native plugin. Zolo signatures describe the
boundary; the function body uses C17 or C++17. These programs run with the CLI
and an installed plugin.
Call C functions with exact integers and import a function from a companion file.
use plugin native::{c}
extern c fn exact(value: int) -> int {
return value;
}
extern c fn length(value: str) -> int {
#include <string.h>
return (int64_t)strlen(value);
}
extern c fn bytes_length(value: bytes) -> int {
return (int64_t)value.len;
}
extern c fn data() -> bytes {
static const unsigned char raw[] = {0, 127, 255};
zolo_bytes value = {raw, sizeof(raw)};
return value;
}
extern c fn call(callback: fn(int) -> int) -> int {
zolo_value input = zolo_i64(40), output = zolo_nil();
int status = zolo_callback_call(callback, &input, 1, &output);
int64_t value = output.integer;
zolo_callback_release(callback, &output);
return status == 0 ? value : -1;
}
print(exact(9007199254740993)) // expected: 9007199254740993
print(length("hello C")) // expected: 7
print(bytes_length(data())) // expected: 3
print(call(|value| value + 2)) // expected: 42
Requires the Zolo CLI/host — open in the playground or run locally.
Construct a public C++ class with .new, call methods and await a native operation.
use plugin native::{cpp}
extern cpp from "./native_fixtures/Person.cpp" use {Person}
extern cpp fn greet(name: str) -> str {
return "Hello " + name;
}
extern cpp async fn later(value: int) -> int {
#include <chrono>
#include <thread>
std::this_thread::sleep_for(std::chrono::milliseconds(10));
return value + 1;
}
extern cpp fn call(callback: fn(int) -> int) -> int {
return callback(40);
}
let person = Person.new(name: "Ana", age: 30)
print(person.greet()) // expected: Hello Ana
print(person.birthday()) // expected: 31
person.age = 32
print(person.age) // expected: 32
print(Person.twice(21)) // expected: 42
print(greet("C++")) // expected: Hello C++
print(await later(41)) // expected: 42
print(call(|value| value + 2)) // expected: 42
Requires the Zolo CLI/host — open in the playground or run locally.
int maps to signed 64-bit integers, float to double, and str to a
length-aware UTF-8 adapter in C or std::string in C++. Narrow integer
conversions are checked. C strings reject embedded NUL. Collections and copied
records use the explicit zolo_value adapter described in the plugin guide.
Pointers, ownership-dependent APIs, varargs and open templates need a concrete
wrapper with a supported signature.
Paths follow the importing Zolo file:
extern cpp from "./Person.cpp" use {Person}.
Public C++ constructors, methods, fields and static methods are available
through ordinary Zolo calls. Objects retain their native state and identity
within the compiled module.
Callbacks and async
C++ callback parameters such as fn(int) -> int become a callable adapter:
the authored body can call callback(41). C uses zolo_callback_call and
zolo_callback_release from the bridge header. Callbacks borrow their lifetime
from the current invocation and support nested Zolo calls. Do not retain them
or invoke them from an unrelated native thread.
extern cpp async fn schedules native work on an invocation worker.
await returns its result while callbacks run on the owning Zolo runtime.
Cancellation closes callback and result delivery; native work may continue
until its own cancellation mechanism stops it. Arbitrary C++ futures need an
explicit adapter.
Libraries and deployment
Declare vcpkg ports once for the provider:
Prepare fmt once and preserve an exact integer through native formatting.
use plugin native::{cpp}
// zolo install prepares the pinned vcpkg library once; auto policy may prepare
// it at the first run. Prepared executables reuse sealed library bytes.
extern cpp deps {
fmt = { version = "11.0.2", default_features = true }
}
extern cpp fn formatted(value: int) -> str {
#include <fmt/format.h>
return fmt::format("exact {}", value);
}
print(formatted(9007199254740993)) // expected: exact 9007199254740993
Requires the Zolo CLI/host — open in the playground or run locally.
use plugin native::{cpp}
extern cpp deps {
"fmt" = "11.0.2"
}
extern cpp fn message(value: int) -> str {
#include <fmt/format.h>
return fmt::format("answer: {}", value);
}
print(message(42))
Prepare explicitly with zolo install main.zolo, then run with
zolo run main.zolo --offline --frozen. Projects use
[foreign.native.dependencies] in zolo.toml. The selected vcpkg baseline,
triplet, features and CRT become part of the locked environment. On Windows,
the default is x64-windows-static; choose a compatible triplet deliberately.
Preparation needs Clang and the platform's native headers/linker.
ZOLO_CLANG selects Clang. Editor queries additionally use clangd and never
load authored code or execute its initializers. Compiled artifacts retain their
native library, package assets and source snapshots. VM, native and LLVM use the
same artifact, including dynamic, embedded and static plugin packaging, without
the original source or compiler at deployment.
C++ exceptions become Zolo errors with an authored function frame. Precise inner throw statements require native debug information. Native crashes and undefined behavior retain their native process semantics. Hosted wasm-aot execution is unavailable. Runtime acceptance currently covers Windows x64; other platforms need independent validation.
See also