5.3.14. C++ Integration: Serialization
This tutorial shows how to serialize a compiled daslang program to a binary blob and deserialize it, skipping recompilation on subsequent runs. Topics covered:
AstSerializer— the serializer/deserializerSerializationStorageVector— in-memory serialization bufferProgram::serialize()— serializing a compiled programThe compile → serialize → deserialize → simulate workflow
5.3.14.1. Prerequisites
Tutorial 13 completed (tutorial_integration_cpp_aot).
5.3.14.2. Why serialize?
Compiling a daslang program involves parsing, type inference, and optimization — this can take noticeable time for large scripts. Serialization saves the compiled program to a binary blob so that future runs can skip compilation entirely:
First run — compile from source, serialize to file/buffer
Subsequent runs — deserialize from blob, simulate, run
This is useful for:
Faster startup in production applications
Distributing pre-compiled scripts
Caching compiled programs in editors and build pipelines
5.3.14.3. Required header
#include "daScript/ast/ast_serializer.h"
5.3.14.4. The serialization workflow
5.3.14.4.1. Stage 1 — Compile from source
auto program = compileDaScript(scriptPath, fAccess, tout, libGroup);
// Must simulate once before serializing
Context ctx(program->getContextStackSize());
program->simulate(ctx, tout);
5.3.14.4.2. Stage 2 — Serialize to memory
auto writeTo = make_unique<SerializationStorageVector>();
{
AstSerializer ser(writeTo.get(), true); // writing = true
program->serialize(ser);
ser.moduleLibrary = nullptr;
}
size_t blobSize = writeTo->buffer.size();
program.reset(); // release original program
SerializationStorageVector wraps a vector<uint8_t> buffer.
After serialization, the buffer contains the entire compiled program.
5.3.14.4.3. Stage 3 — Deserialize
auto readFrom = make_unique<SerializationStorageVector>();
readFrom->buffer = das::move(writeTo->buffer);
{
AstSerializer deser(readFrom.get(), false); // writing = false
program = make_smart<Program>();
program->serialize(deser);
deser.moduleLibrary = nullptr;
}
Note that Program::serialize() is used for both directions —
the AstSerializer constructor’s isWriting flag determines
the mode.
5.3.14.4.4. Stage 4 — Simulate and run
Context ctx(program->getContextStackSize());
program->simulate(ctx, tout);
auto fn = ctx.findFunction("test");
ctx.evalWithCatch(fn, nullptr);
The deserialized program works identically to a freshly compiled one.
5.3.14.5. Saving to and loading from disk
To persist across application restarts, write the buffer to a file:
// Save
FILE * f = fopen("script.cache", "wb");
fwrite(writeTo->buffer.data(), 1, writeTo->buffer.size(), f);
fclose(f);
// Load
auto readFrom = make_unique<SerializationStorageVector>();
FILE * f2 = fopen("script.cache", "rb");
fseek(f2, 0, SEEK_END);
size_t sz = ftell(f2);
fseek(f2, 0, SEEK_SET);
readFrom->buffer.resize(sz);
fread(readFrom->buffer.data(), 1, sz, f2);
fclose(f2);
5.3.14.6. Building and running
cmake --build build --config Release --target integration_cpp_14
bin\Release\integration_cpp_14.exe
Expected output:
=== Stage 1: Compile from source ===
Compiled successfully.
Simulated successfully.
=== Stage 2: Serialize ===
Serialized size: 5022 bytes
Original program released.
=== Stage 3: Deserialize ===
Deserialized successfully.
=== Stage 4: Simulate and run ===
=== Serialization Tutorial ===
Hello, World!
sum_to(10) = 55
sum_to(100) = 5050
See also
Full source:
14_serialization.cpp,
14_serialization.das
Previous tutorial: tutorial_integration_cpp_aot
Next tutorial: tutorial_integration_cpp_custom_annotations