forked from saucer/saucer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
125 lines (105 loc) · 4.42 KB
/
main.cpp
File metadata and controls
125 lines (105 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <saucer/smartview.hpp>
#include <chrono>
#include <thread>
static constexpr const char *demo = R"html(
<!DOCTYPE html>
<html>
<body>
<h1>Welcome to saucer!</h1>
<p>This example demonstrates how to use the JS <-> C++ Brdige</p>
<hr>
<p>The C++ code currently exposes the following functions:<p>
<ul>
<li>add(number, number)</li>
<li>add_random(number, number)</li>
<li>add_object({ a: number, b: number })</li>
<li>divide(number, number)</li>
<li>divide_slow(number, number)</li>
<li>divide_random(number, number)</li>
</ul>
<p>You can use the Dev-Tools to call them!</p>
<p>The following two variants of function invocation exist:</p>
<ul>
<li>await saucer.call("add", [10, 5]);</li>
<li>await saucer.exposed.add(10, 5);</li>
</ul>
<p>The function arguments will automatically be type-checked!</p>
</body>
</html>
)html";
struct simple_aggregate
{
double a;
double b;
};
coco::stray start(saucer::application *app)
{
auto window = saucer::window::create(app).value();
auto webview = saucer::smartview::create({.window = window});
webview->expose("add",
[](double a, double b)
{
// A simple exposed function. Takes two doubles, returns a double.
return a + b;
});
webview->expose("add_random",
[&](double a, double b) -> coco::task<double>
{
// We can also use `evaluate` to evaluate JavaScript code and capture its result:
auto random = *co_await webview->evaluate<double>("Math.random()");
co_return a + b + random;
});
webview->expose("add_object",
[](const simple_aggregate &aggregate)
{
// Arbitrary types? No problem. See the docs for usage with more complex types.
return aggregate.a + aggregate.b;
});
webview->expose("divide",
[](double a, double b) -> std::expected<double, std::string>
{
if (b == 0)
{
// We can use `std::unexpected` to reject the promise
return std::unexpected{"Second operand must not be zero"};
}
return a / b;
});
webview->expose("divide_slow",
[](double a, double b, saucer::executor<double> executor) mutable
{
// When taking a `saucer::executor` as the last argument, you have more control over when to resolve/reject the
// promise. We can pass the executor to a thread and resolve it sometime later.
std::thread t(
[a, b, executor = std::move(executor)]
{
std::this_thread::sleep_for(std::chrono::seconds(5));
const auto &[resolve, reject] = executor;
if (b == 0)
{
return reject("Second operand must not be zero");
}
return resolve(a / b);
});
t.detach();
});
webview->expose("divide_random",
[&](double a, double b) -> coco::task<std::expected<double, std::string>>
{
// Remember how we used `std::expected` earlier to reject the promise?
// Works the same way for a coroutine that returns `std::expected`!
if (b == 0)
{
co_return std::unexpected{"Second operand must not be zero"};
}
co_return (a / b) / *co_await webview->evaluate<double>("Math.random()");
});
webview->set_dev_tools(true);
webview->set_html(demo);
window->show();
co_await app->finish();
}
int main()
{
return saucer::application::create({.id = "example"})->run(start);
}