Skip to content

Commit 930d354

Browse files
MangoPeachGraperockwotjlanfeust69
authored
c-api: Create and instantiate a component model linker (#10598)
* c-api: Create and instantiate a component model linker Co-authored-by: Tyler Rockwood <[email protected]> Co-authored-by: Jean-Jacques Lafay <[email protected]> * c-api: Accept `wat` in `wasmtime_component_new()` * Add a test * c-api: Include `wasmtime/conf.h` in `component/component.h` * Add `wasmtime/conf.h` include to `instance.h` and `linker.h` * Make wasmtime_component_instance_t non-opaque * Defer `wasmtime_component_linker_instance()` --------- Co-authored-by: Tyler Rockwood <[email protected]> Co-authored-by: Jean-Jacques Lafay <[email protected]>
1 parent fc3302a commit 930d354

File tree

9 files changed

+190
-14
lines changed

9 files changed

+190
-14
lines changed

Diff for: crates/c-api/include/wasmtime/component.h

+2
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@
22
#define WASMTIME_COMPONENT_H
33

44
#include <wasmtime/component/component.h>
5+
#include <wasmtime/component/instance.h>
6+
#include <wasmtime/component/linker.h>
57

68
#endif // WASMTIME_COMPONENT_H

Diff for: crates/c-api/include/wasmtime/component/component.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#ifndef WASMTIME_COMPONENT_COMPONENT_H
22
#define WASMTIME_COMPONENT_COMPONENT_H
33

4-
#ifdef WASMTIME_FEATURE_COMPONENT_MODEL
5-
64
#include <wasm.h>
5+
#include <wasmtime/conf.h>
76
#include <wasmtime/error.h>
87

8+
#ifdef WASMTIME_FEATURE_COMPONENT_MODEL
9+
910
#ifdef __cplusplus
1011
extern "C" {
1112
#endif

Diff for: crates/c-api/include/wasmtime/component/instance.h

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef WASMTIME_COMPONENT_INSTANCE_H
2+
#define WASMTIME_COMPONENT_INSTANCE_H
3+
4+
#include <wasmtime/conf.h>
5+
6+
#ifdef WASMTIME_FEATURE_COMPONENT_MODEL
7+
8+
#ifdef __cplusplus
9+
extern "C" {
10+
#endif
11+
12+
/// \brief Representation of a instance in Wasmtime.
13+
///
14+
/// Instances are represented with a 64-bit identifying integer in Wasmtime.
15+
/// They do not have any destructor associated with them. Instances cannot
16+
/// interoperate between #wasmtime_store_t instances and if the wrong instance
17+
/// is passed to the wrong store then it may trigger an assertion to abort the
18+
/// process.
19+
typedef struct wasmtime_component_instance {
20+
/// Internal identifier of what store this belongs to, never zero.
21+
uint64_t store_id;
22+
/// Internal index within the store.
23+
size_t index;
24+
} wasmtime_component_instance_t;
25+
26+
#ifdef __cplusplus
27+
} // extern "C"
28+
#endif
29+
30+
#endif // WASMTIME_FEATURE_COMPONENT_MODEL
31+
32+
#endif // WASMTIME_COMPONENT_INSTANCE_H

Diff for: crates/c-api/include/wasmtime/component/linker.h

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#ifndef WASMTIME_COMPONENT_LINKER_H
2+
#define WASMTIME_COMPONENT_LINKER_H
3+
4+
#include <wasm.h>
5+
#include <wasmtime/component/component.h>
6+
#include <wasmtime/component/instance.h>
7+
#include <wasmtime/conf.h>
8+
#include <wasmtime/error.h>
9+
#include <wasmtime/store.h>
10+
11+
#ifdef WASMTIME_FEATURE_COMPONENT_MODEL
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
typedef struct wasmtime_component_linker_t wasmtime_component_linker_t;
18+
19+
/**
20+
* \brief Creates a new #wasmtime_component_linker_t for the specified engine.
21+
*
22+
* \param engine the compilation environment and configuration
23+
*
24+
* \return a pointer to the newly created #wasmtime_component_linker_t
25+
*/
26+
WASM_API_EXTERN wasmtime_component_linker_t *
27+
wasmtime_component_linker_new(const wasm_engine_t *engine);
28+
29+
/**
30+
* \brief Instantiates a component instance in a given #wasmtime_context_t
31+
*
32+
* \param linker a #wasmtime_component_linker_t that will help provide host
33+
* functions
34+
* \param context the #wasmtime_context_t in which the instance should be
35+
* created
36+
* \param component the #wasmtime_component_t to instantiate
37+
* \param instance_out on success, the instantiated
38+
* #wasmtime_component_instance_t
39+
*
40+
* \return wasmtime_error_t* on success `NULL` is returned, otherwise an error
41+
* is returned which describes why the build failed.
42+
*/
43+
WASM_API_EXTERN wasmtime_error_t *wasmtime_component_linker_instantiate(
44+
const wasmtime_component_linker_t *linker, wasmtime_context_t *context,
45+
const wasmtime_component_t *component,
46+
wasmtime_component_instance_t *instance_out);
47+
48+
/**
49+
* \brief Deletes a #wasmtime_component_linker_t created by
50+
* #wasmtime_component_linker_new
51+
*
52+
* \param linker the #wasmtime_component_linker_t to delete
53+
*/
54+
WASM_API_EXTERN void
55+
wasmtime_component_linker_delete(wasmtime_component_linker_t *linker);
56+
57+
#ifdef __cplusplus
58+
} // extern "C"
59+
#endif
60+
61+
#endif // WASMTIME_FEATURE_COMPONENT_MODEL
62+
63+
#endif // WASMTIME_COMPONENT_LINKER_H

Diff for: crates/c-api/src/component/component.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,10 @@ pub unsafe extern "C" fn wasmtime_component_new(
2424
len: usize,
2525
component_out: &mut *mut wasmtime_component_t,
2626
) -> Option<Box<wasmtime_error_t>> {
27-
let binary = unsafe { crate::slice_from_raw_parts(buf, len) };
28-
crate::handle_result(
29-
Component::from_binary(&engine.engine, binary),
30-
|component| {
31-
*component_out = Box::into_raw(Box::new(wasmtime_component_t { component }));
32-
},
33-
)
27+
let bytes = unsafe { crate::slice_from_raw_parts(buf, len) };
28+
crate::handle_result(Component::new(&engine.engine, bytes), |component| {
29+
*component_out = Box::into_raw(Box::new(wasmtime_component_t { component }));
30+
})
3431
}
3532

3633
#[unsafe(no_mangle)]

Diff for: crates/c-api/src/component/linker.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use wasmtime::component::{Instance, Linker};
2+
3+
use crate::{wasm_engine_t, wasmtime_error_t, WasmtimeStoreContextMut, WasmtimeStoreData};
4+
5+
use super::wasmtime_component_t;
6+
7+
#[repr(transparent)]
8+
pub struct wasmtime_component_linker_t {
9+
pub(crate) linker: Linker<WasmtimeStoreData>,
10+
}
11+
12+
#[unsafe(no_mangle)]
13+
pub unsafe extern "C" fn wasmtime_component_linker_new(
14+
engine: &wasm_engine_t,
15+
) -> Box<wasmtime_component_linker_t> {
16+
Box::new(wasmtime_component_linker_t {
17+
linker: Linker::new(&engine.engine),
18+
})
19+
}
20+
21+
#[unsafe(no_mangle)]
22+
pub unsafe extern "C" fn wasmtime_component_linker_instantiate(
23+
linker: &wasmtime_component_linker_t,
24+
context: WasmtimeStoreContextMut<'_>,
25+
component: &wasmtime_component_t,
26+
instance_out: &mut Instance,
27+
) -> Option<Box<wasmtime_error_t>> {
28+
let result = linker.linker.instantiate(context, &component.component);
29+
crate::handle_result(result, |instance| *instance_out = instance)
30+
}
31+
32+
#[unsafe(no_mangle)]
33+
pub unsafe extern "C" fn wasmtime_component_linker_delete(
34+
_linker: Box<wasmtime_component_linker_t>,
35+
) {
36+
}

Diff for: crates/c-api/src/component/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
mod component;
2+
mod linker;
23

34
pub use component::*;
5+
pub use linker::*;

Diff for: crates/c-api/tests/CMakeLists.txt

+6-5
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ FetchContent_MakeAvailable(googletest)
99

1010
include(GoogleTest)
1111

12-
function(add_capi_test name)
13-
add_executable(test-${name} ${name}.cc)
12+
function(add_capi_test name path)
13+
add_executable(test-${name} ${path})
1414
target_link_libraries(test-${name} PRIVATE wasmtime-cpp gtest_main)
1515
gtest_discover_tests(test-${name})
1616
endfunction()
1717

18-
add_capi_test(simple)
19-
add_capi_test(types)
20-
add_capi_test(func)
18+
add_capi_test(simple simple.cc)
19+
add_capi_test(types types.cc)
20+
add_capi_test(func func.cc)
21+
add_capi_test(component-instantiate component/instantiate.cc)
2122

2223
# Add a custom test where two files include `wasmtime.hh` and are compiled into
2324
# the same executable (basically makes sure any defined functions in the header

Diff for: crates/c-api/tests/component/instantiate.cc

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include <gtest/gtest.h>
2+
#include <wasmtime.h>
3+
4+
TEST(component, instantiate) {
5+
static constexpr auto bytes = std::string_view{
6+
R"END(
7+
(component
8+
(core module)
9+
)
10+
)END",
11+
};
12+
13+
const auto engine = wasm_engine_new();
14+
EXPECT_NE(engine, nullptr);
15+
16+
const auto store = wasmtime_store_new(engine, nullptr, nullptr);
17+
EXPECT_NE(store, nullptr);
18+
const auto context = wasmtime_store_context(store);
19+
EXPECT_NE(context, nullptr);
20+
21+
wasmtime_component_t *component = nullptr;
22+
23+
auto error = wasmtime_component_new(
24+
engine, reinterpret_cast<const uint8_t *>(bytes.data()), bytes.size(),
25+
&component);
26+
27+
EXPECT_EQ(error, nullptr);
28+
EXPECT_NE(component, nullptr);
29+
30+
const auto linker = wasmtime_component_linker_new(engine);
31+
EXPECT_NE(linker, nullptr);
32+
33+
wasmtime_component_instance_t instance = {};
34+
error = wasmtime_component_linker_instantiate(linker, context, component,
35+
&instance);
36+
EXPECT_EQ(error, nullptr);
37+
38+
wasmtime_component_linker_delete(linker);
39+
40+
wasmtime_store_delete(store);
41+
wasm_engine_delete(engine);
42+
}

0 commit comments

Comments
 (0)