-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
37 changed files
with
3,359 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,3 +9,4 @@ | |
/flamegraph.svg | ||
/perf.data | ||
/perf.data.* | ||
/builddir |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "rune-capi" | ||
version = "0.0.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
[lib] | ||
name = "rune" | ||
crate-type = ["staticlib", "cdylib"] | ||
|
||
[dependencies] | ||
rune = { package = "rune", path = "../crates/rune", features = ["ffi"] } | ||
cbindgen = "0.20.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Rune C API | ||
|
||
This crate is not intended to be published, but instead contains the necessary | ||
bindings to provide a C API for Rune. | ||
|
||
## Building and running examples | ||
|
||
Examples are built using meson, and requires that the static library is already | ||
built and available in `target/debug` (or `target/release`). Note that for | ||
cbindgen to work it requires `+nightly`. | ||
|
||
``` | ||
cargo build --package rune-capi | ||
meson setup builddir capi | ||
ninja -C builddir | ||
``` | ||
|
||
After this, you can find the binaries corresponding to their names in | ||
[`examples`](examples) in `target/builddir`. | ||
|
||
When building and running on Windows you might have to run through the [MSVC | ||
development | ||
shell](https://docs.microsoft.com/en-us/visualstudio/ide/reference/command-prompt-powershell) | ||
to have access to the C compiler. | ||
|
||
## Regenerating header file | ||
|
||
Since we use macros, the header can only be regenerated using `+nightly`. | ||
|
||
```sh | ||
cargo +nightly run --package rune-capi --bin cbindgen | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
language = "C" | ||
include_guard = "RUNE_H" | ||
no_includes = true | ||
sys_includes = ["stdbool.h", "stdint.h", "stddef.h"] | ||
cpp_compat = true | ||
documentation_style = "doxy" | ||
|
||
style = "type" | ||
|
||
[export.rename] | ||
"Build" = "rune_build" | ||
"ColorChoice" = "rune_color_choice" | ||
"Context" = "rune_context" | ||
"ContextError" = "rune_context_error" | ||
"Diagnostics" = "rune_diagnostics" | ||
"Hash" = "rune_hash" | ||
"Module" = "rune_module" | ||
"RuntimeContext" = "rune_runtime_context" | ||
"Source" = "rune_source" | ||
"Sources" = "rune_sources" | ||
"Stack" = "rune_stack" | ||
"StandardStream" = "rune_standard_stream" | ||
"Unit" = "rune_unit" | ||
"Value" = "rune_value" | ||
"Vm" = "rune_vm" | ||
"VmError" = "rune_vm_error" | ||
"StaticType" = "rune_static_type" | ||
|
||
[parse.expand] | ||
crates = ["rune-capi"] | ||
|
||
[enum] | ||
rename_variants = "ScreamingSnakeCase" | ||
prefix_with_name = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#include <assert.h> | ||
#include <stdio.h> | ||
|
||
#include <rune.h> | ||
|
||
/** | ||
* A custom C function that interacts with Rune. This is registered below with | ||
* rune_module_function. | ||
*/ | ||
void custom_function(rune_stack *stack, uintptr_t count, rune_vm_error *e) { | ||
rune_value value = rune_value_unit(); | ||
|
||
if (count != 1) { | ||
rune_vm_error_bad_argument_count(e, count, 1); | ||
return; | ||
} | ||
|
||
// Note: Error will be automatically propagated since it's used as an output | ||
// argument. | ||
if (!rune_stack_pop_value(stack, &value, e)) { | ||
return; | ||
} | ||
|
||
int64_t integer = 0; | ||
|
||
if (!rune_value_as_integer(&value, &integer)) { | ||
rune_vm_error_bad_argument_at(e, 0, &value, RUNE_INTEGER_TYPE); | ||
return; | ||
} | ||
|
||
rune_stack_push_unit(stack); | ||
rune_stack_push_integer(stack, integer * 10); | ||
rune_stack_push_tuple(stack, 2, e); | ||
} | ||
|
||
int main() { | ||
rune_context context = rune_context_new(); | ||
rune_module module = rune_module_new(); | ||
rune_runtime_context runtime = rune_runtime_context_new(); | ||
rune_sources sources = rune_sources_new(); | ||
rune_standard_stream out = rune_standard_stream_stderr(RUNE_COLOR_CHOICE_ALWAYS); | ||
rune_unit unit = rune_unit_new(); | ||
rune_vm vm = rune_vm_new(); | ||
rune_vm_error error = rune_vm_error_new(); | ||
rune_context_error context_error = rune_context_error_new(); | ||
|
||
if (!rune_module_function(&module, "test", custom_function, &context_error)) { | ||
rune_context_error_emit(&context_error, &out); | ||
goto EXIT; | ||
} | ||
|
||
if (!rune_context_install(&context, &module, &context_error)) { | ||
rune_context_error_emit(&context_error, &out); | ||
goto EXIT; | ||
} | ||
|
||
rune_module_free(&module); | ||
|
||
rune_source source = rune_source_new("<in>", "pub fn main(n) { test(n) }"); | ||
assert(rune_sources_insert(&sources, &source)); | ||
rune_source_free(&source); | ||
|
||
rune_diagnostics diag = rune_diagnostics_new(); | ||
|
||
rune_build build = rune_build_prepare(&sources); | ||
rune_build_with_diagnostics(&build, &diag); | ||
rune_build_with_context(&build, &context); | ||
|
||
bool ok = rune_build_build(&build, &unit); | ||
|
||
if (!rune_diagnostics_is_empty(&diag)) { | ||
assert(rune_diagnostics_emit(&diag, &out, &sources)); | ||
} | ||
|
||
rune_diagnostics_free(&diag); | ||
|
||
if (!ok) { | ||
goto EXIT; | ||
} | ||
|
||
assert(rune_context_runtime(&context, &runtime)); | ||
assert(rune_vm_setup(&vm, &runtime, &unit)); | ||
|
||
rune_hash entry = rune_hash_name("main"); | ||
|
||
if (!rune_vm_set_entrypoint(&vm, entry, 1, &error)) { | ||
assert(rune_vm_error_emit(&error, &out, &sources)); | ||
goto EXIT; | ||
} | ||
|
||
rune_stack_push_integer(rune_vm_stack_mut(&vm), 42); | ||
rune_value ret = rune_value_unit(); | ||
|
||
if (!rune_vm_complete(&vm, &ret, &error)) { | ||
assert(rune_vm_error_emit(&error, &out, &sources)); | ||
} | ||
|
||
int64_t output = 0; | ||
|
||
if (rune_value_as_integer(&ret, &output)) { | ||
printf("output = %lld\n", output); | ||
} else { | ||
rune_hash type_hash = rune_hash_empty(); | ||
|
||
if (rune_value_type_hash(&ret, &type_hash, &error)) { | ||
printf("output = %lld\n", type_hash); | ||
} else { | ||
printf("output = ?\n"); | ||
} | ||
} | ||
|
||
rune_value_free(&ret); | ||
|
||
EXIT: | ||
rune_context_free(&context); | ||
rune_module_free(&module); | ||
rune_runtime_context_free(&runtime); | ||
rune_sources_free(&sources); | ||
rune_standard_stream_free(&out); | ||
rune_unit_free(&unit); | ||
rune_vm_error_free(&error); | ||
rune_vm_free(&vm); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#include <assert.h> | ||
#include <stdio.h> | ||
|
||
#include <rune.h> | ||
|
||
int main() { | ||
rune_context context = rune_context_new(); | ||
rune_runtime_context runtime = rune_runtime_context_new(); | ||
rune_sources sources = rune_sources_new(); | ||
rune_standard_stream out = rune_standard_stream_stderr(RUNE_COLOR_CHOICE_ALWAYS); | ||
rune_unit unit = rune_unit_new(); | ||
rune_vm vm = rune_vm_new(); | ||
rune_vm_error error = rune_vm_error_new(); | ||
|
||
rune_source source = rune_source_new("<in>", "pub fn add_one(n) { n / 3 }"); | ||
assert(rune_sources_insert(&sources, &source)); | ||
rune_source_free(&source); | ||
|
||
rune_diagnostics diag = rune_diagnostics_new(); | ||
|
||
rune_build build = rune_build_prepare(&sources); | ||
rune_build_with_diagnostics(&build, &diag); | ||
|
||
bool ok = rune_build_build(&build, &unit); | ||
|
||
if (!rune_diagnostics_is_empty(&diag)) { | ||
assert(rune_diagnostics_emit(&diag, &out, &sources)); | ||
} | ||
|
||
rune_diagnostics_free(&diag); | ||
|
||
if (!ok) { | ||
goto EXIT; | ||
} | ||
|
||
assert(rune_context_runtime(&context, &runtime)); | ||
assert(rune_vm_setup(&vm, &runtime, &unit)); | ||
|
||
rune_hash entry = rune_hash_name("add_one"); | ||
|
||
if (!rune_vm_set_entrypoint(&vm, entry, 1, &error)) { | ||
assert(rune_vm_error_emit(&error, &out, &sources)); | ||
goto EXIT; | ||
} | ||
|
||
rune_stack_push_integer(rune_vm_stack_mut(&vm), 42); | ||
rune_value ret = rune_value_unit(); | ||
|
||
if (!rune_vm_complete(&vm, &ret, &error)) { | ||
assert(rune_vm_error_emit(&error, &out, &sources)); | ||
} | ||
|
||
int64_t output = 0; | ||
|
||
if (rune_value_as_integer(&ret, &output)) { | ||
printf("output = %lld\n", output); | ||
} else { | ||
printf("output = ?\n"); | ||
} | ||
|
||
rune_value_free(&ret); | ||
|
||
EXIT: | ||
rune_context_free(&context); | ||
rune_runtime_context_free(&runtime); | ||
rune_sources_free(&sources); | ||
rune_standard_stream_free(&out); | ||
rune_unit_free(&unit); | ||
rune_vm_error_free(&error); | ||
rune_vm_free(&vm); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#include <assert.h> | ||
#include <stdio.h> | ||
|
||
#include <rune.h> | ||
|
||
int main() { | ||
rune_value a = rune_value_integer(42); | ||
rune_value b = rune_value_bool(false); | ||
rune_vm_error error = rune_vm_error_new(); | ||
|
||
assert(rune_value_type_hash_or_empty(&a) == RUNE_INTEGER_TYPE_HASH); | ||
assert(rune_value_type_hash_or_empty(&b) == RUNE_BOOL_TYPE_HASH); | ||
|
||
rune_vm_error_free(&error); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
project('examples', 'c') | ||
|
||
c = meson.get_compiler('c') | ||
|
||
inc = include_directories('.') | ||
|
||
dirs = [ | ||
meson.current_source_dir() + '/../target/debug', | ||
meson.current_source_dir() + '/../target/release', | ||
] | ||
|
||
extra = [] | ||
|
||
if host_machine.system() == 'windows' | ||
extra = [ | ||
c.find_library('ws2_32', required: true), | ||
c.find_library('bcrypt', required: true), | ||
c.find_library('userenv', required: true), | ||
] | ||
endif | ||
|
||
rune_dep = c.find_library('rune', dirs: dirs, required: false) | ||
|
||
if not rune_dep.found() | ||
error('Could not find rune library, try: cargo build --package rune-capi') | ||
endif | ||
|
||
deps = [rune_dep] + extra | ||
|
||
executable('function', 'examples/function.c', dependencies: deps, include_directories: inc) | ||
executable('minimal', 'examples/minimal.c', dependencies: deps, include_directories: inc) | ||
executable('type_hash', 'examples/type_hash.c', dependencies: deps, include_directories: inc) |
Oops, something went wrong.