Libraries Guide
Create, distribute, and use reusable Strada libraries.
Overview
Strada supports two types of libraries:
Shared Libraries (.so)
Dynamically loaded at runtime. Use import_lib to import.
Best for: Plugins, optional features, reducing executable size
Object Files (.o)
Statically linked at compile time. Use import_object to import.
Best for: Core libraries, single-file distribution, faster startup
Creating a Library
Step 1: Write Your Library
Create a Strada file with a package declaration and optional version:
# lib/MathLib.strada
package MathLib;
version "1.0.0";
func add(int $a, int $b) int {
return $a + $b;
}
func multiply(int $a, int $b) int {
return $a * $b;
}
func factorial(int $n) int {
if ($n <= 1) {
return 1;
}
return $n * factorial($n - 1);
}
func add() becomes MathLib_add() internally.
Step 2: Compile the Library
For shared libraries (.so):
./strada --shared lib/MathLib.strada
mv MathLib.so lib/
For object files (.o):
./strada --object lib/MathLib.strada
mv MathLib.o lib/
.so and .o files via __strada_export_info(). You don't need to keep the original .strada source file.
Using Shared Libraries (import_lib)
Shared libraries are loaded at runtime using dlopen(). They're loaded lazily on first function call.
Basic Usage
use lib "lib"; # Add lib/ to search path
import_lib "MathLib"; # Import MathLib.so
func main() int {
# Call with namespace syntax (recommended)
my int $sum = MathLib::add(10, 32);
my int $product = MathLib::multiply(6, 7);
my int $fact = MathLib::factorial(5);
say("Sum: " . $sum); # 42
say("Product: " . $product); # 42
say("Factorial: " . $fact); # 120
return 0;
}
Requirements
| File | Purpose | Required |
|---|---|---|
LibName.so | Compiled code + embedded metadata | Yes |
LibName.strada | Source (only needed for recompiling) | No |
How It Works
- At compile time: Compiler loads
MathLib.soand calls__strada_export_info()to extract function signatures - Compiler generates wrapper functions that call into the shared library
- At runtime: First call to any library function loads
MathLib.soviadlopen() - Subsequent calls use cached function pointers
Using Object Files (import_object)
Object files are linked directly into your executable at compile time. The result is a single, self-contained binary.
Basic Usage
use lib "lib"; # Add lib/ to search path
import_object "MathLib"; # Link MathLib.o statically
func main() int {
# Same syntax as import_lib
my int $sum = MathLib::add(10, 32);
say($sum); # 42
return 0;
}
Requirements
| File | Purpose | Required |
|---|---|---|
LibName.o | Compiled code + embedded metadata | Yes |
LibName.strada | Source (only needed for recompiling) | No |
How It Works
- At compile time: Compiler extracts metadata from
MathLib.oby calling__strada_export_info() - Generates direct function calls (no wrappers needed)
- Links
MathLib.ointo the final executable with gcc
Shared vs Object: When to Use Which
| Feature | Shared (.so) | Object (.o) |
|---|---|---|
| Linking | Runtime (dlopen) | Compile time (gcc) |
| Distribution | Multiple files | Single executable |
| Startup time | Slightly slower (lazy load) | Faster |
| Memory sharing | Shared between processes | Per-process |
| Updates | Replace .so without recompile | Requires recompile |
| Plugins | Excellent | Not suitable |
import_object for core libraries you always need. Use import_lib for optional features or plugins.
Library Search Paths
The compiler searches for libraries in this order:
- Current directory
- Paths added with
use lib "path"(in order) - Paths added with
-L pathflag (high priority) - Paths added with
-LL pathflag (low priority)
# Multiple search paths
use lib "lib";
use lib "vendor/lib";
use lib "/usr/local/strada/lib";
import_lib "JSON"; # Searches all paths for JSON.so and JSON.strada
import_object "Utils"; # Searches all paths for Utils.o and Utils.strada
Library Versioning
Add a version to your library with the version statement:
package JSON;
version "2.1.0";
func encode(scalar $data) str {
# ...
}
Retrieve the version at runtime:
my int $lib = sys::dl_open("lib/JSON.so");
my int $fn = sys::dl_sym($lib, "__strada_version");
my str $version = sys::dl_call_version($fn);
say("JSON version: " . $version); # "2.1.0"
Inspecting Libraries
Use the soinfo tool to inspect compiled libraries:
# View library information
./tools/soinfo lib/JSON.so
# Show usage examples
./tools/soinfo --examples lib/JSON.so
Example output:
Library: lib/JSON.so
Package: JSON
Version: 2.1.0
Exported functions:
JSON_encode(scalar $data) -> str
JSON_decode(str $json) -> scalar
JSON_pretty(scalar $data) -> str
Call examples:
my str $result = JSON::encode($data);
my scalar $result = JSON::decode($json);
my str $result = JSON::pretty($data);
Complete Example: JSON Library
1. Create the Library
# lib/JSON.strada
package JSON;
version "1.0.0";
func encode(scalar $data) str {
return json_encode($data);
}
func decode(str $json) scalar {
return json_decode($json);
}
func pretty(scalar $data) str {
# Pretty print with indentation
return json_encode_pretty($data, 2);
}
2. Compile
# As shared library
./strada --shared lib/JSON.strada && mv JSON.so lib/
# Or as object file
./strada --object lib/JSON.strada && mv JSON.o lib/
3. Use in Your Program
# app.strada
use lib "lib";
import_lib "JSON"; # or: import_object "JSON"
func main() int {
# Create some data
my hash %user = {
"name" => "Alice",
"age" => 30,
"roles" => ["admin", "user"]
};
# Encode to JSON
my str $json = JSON::encode(\%user);
say($json);
# {"name":"Alice","age":30,"roles":["admin","user"]}
# Pretty print
my str $pretty = JSON::pretty(\%user);
say($pretty);
# Decode back
my scalar $decoded = JSON::decode($json);
say($decoded->{"name"}); # Alice
return 0;
}
4. Compile and Run
./strada app.strada
./app
Libraries with C Code
Libraries can include embedded C code using __C__ blocks:
# lib/Compress.strada
package Compress;
version "1.0.0";
__C__ {
#include <zlib.h>
}
func gzip(str $data) str {
__C__ {
char *input = strada_to_str(data);
size_t input_len = strlen(input);
size_t output_len = compressBound(input_len);
char *output = malloc(output_len);
compress((Bytef*)output, &output_len,
(Bytef*)input, input_len);
free(input);
StradaValue *result = strada_new_str_len(output, output_len);
free(output);
return result;
}
}
Compile with additional libraries:
./strada --shared lib/Compress.strada -- -lz
Troubleshooting
Common Errors
| Error | Cause | Solution |
|---|---|---|
cannot find LibName.so |
.so file not in search path | Add use lib "path" or move .so to lib/ |
cannot find LibName.o |
.o file not in search path | Add use lib "path" or move .o to lib/ |
undefined symbol |
Function not exported | Check package name matches function prefix |
missing __strada_export_info |
Old library format | Recompile library with current compiler |