7.2. Exposing native resources
The dependencies field links against shared libraries. The expose
field handles a different need: a module that defines a C++ struct, a
Python class, or an R helper whose definition downstream foreign code
needs to #include (or import, or source) by name. On install,
listed files are copied to per-language well-known paths under
$MORLOC_HOME, namespaced by module name. Downstream code then refers
to them through a stable path that is the same for every consumer.
expose:
cpp: [person.hpp]
py: [__init__.py, helpers/]
r: [util.R]
Each key is optional. Paths are relative to the module root; glob
patterns ( within a segment, * across segments, trailing / for
a directory) follow the same syntax as include. Subtree structure is
preserved on copy — essential for Python packages with init.py
markers and for C++ headers that #include siblings by relative path.
| Language | Destination | Consumer code |
|---|---|---|
C++ |
|
|
Python |
|
|
R |
|
|
For Python, hyphens in the module name are converted to underscores so
the destination is a legal Python identifier (a module tensor-cpp
becomes tensor_cpp). The C subtree `$MORLOC_HOME/include` is
already on every C pool’s -I path, so no compile flags need
tweaking; consumers just write the namespaced #include. morloc
uninstall symmetrically removes the exposed copies alongside the
install dir.
A worked example. The people module declares a Morloc type backed by
a C++ struct and exposes the header that defines it:
module people (Person, makePerson)
import root-cpp
type Cpp => Person = "person_t"
source Cpp from "person.hpp" ("make_person" as makePerson)
makePerson :: Str -> Int -> Person
name: people
version: 0.1.0
expose:
cpp: [person.hpp]
#ifndef PEOPLE_PERSON_HPP
#define PEOPLE_PERSON_HPP
#include <string>
struct person_t {
std::string name;
int age;
};
inline person_t make_person(const std::string& name, int age) {
return person_t{name, age};
}
#endif
Install with morloc install ./people. The exposed header now lives at
$MORLOC_HOME/include/people/person.hpp. A downstream program imports
the Morloc type and uses the underlying C++ struct directly in its own
foreign code:
module main (greeting)
import people (Person, makePerson)
import root-cpp
source Cpp from "src.hpp" ("greet")
greet :: Person -> Str
greeting :: Str
greeting = greet (makePerson "Alice" 30)
#include "people/person.hpp"
#include <string>
inline std::string greet(const person_t& p) {
return "Hello, " + p.name + "! Age " + std::to_string(p.age);
}
The same exposed header is discoverable from non-Morloc C programs
too: compile with `g -I$MORLOC_HOME/include` and #include
"people/person.hpp" works identically.