You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 791367d
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: CHANGES.md
+5-2Lines changed: 5 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,3 @@
1
-
## Master
2
-
3
1
## Version 3.0
4
2
5
3
* Moved to C++17 as minimum supported standard C++ version.
@@ -17,6 +15,11 @@
17
15
* Allow specifying a non virtual base class method when declaring class members (functions or variables) not exposed in the inherited class.
18
16
* Allow using capturing lambdas in `Namespace::addFunction`, `Namespace::addProperty`, `Class<T>::addFunction`, `Class<T>::addStaticFunction`, `Class<T>::addProperty` and `Class<T>::addStaticProperty`.
19
17
* Added multiple inheritance support: `deriveClass` now accepts more than one registered base class (e.g. `deriveClass<D, A, B>`).
18
+
* Added C++20 coroutine integration: `CppCoroutine<R>` type that can be registered via `Namespace::addCoroutine()` to expose C++ generators to Lua using `co_yield` and `co_return`.
19
+
* Added `LuaCoroutine` awaitable to resume a child Lua thread synchronously from inside a `CppCoroutine` body using `co_await`.
20
+
* Added `lua_resume_x` and `lua_isyieldable_x` portable helpers in `LuaBridge/detail/LuaHelpers.h`.
21
+
* Added `LUABRIDGE_HAS_CXX20_COROUTINES` feature-detection macro; opt out with `LUABRIDGE_DISABLE_CXX20_COROUTINES`.
22
+
* Added `ErrorCode::CoroutineYieldFromNonCoroutine` and `ErrorCode::CoroutineAlreadyDone` error codes.
20
23
* Added `Namespace::addVariable` to allow adding a modifiable value by copy into the namespace without incurring in function calls or metatables generation.
21
24
* Added `luabridge::callWithHandler` free function and `LuaRef::callWithHandler` member to provide a custom Lua message handler during `lua_pcall`.
22
25
* Added `luabridge::newFunction` free function and `LuaRef::newFunction` static method to wrap any C++ callable into a Lua function exposed as a `LuaRef`.
*[Appendix - API Reference](#appendix---api-reference)
82
88
@@ -1245,6 +1251,113 @@ When the script calls `useStateAndArgs`, it passes only the integer and string p
1245
1251
1246
1252
The same is applicable for properties.
1247
1253
1254
+
2.9 - C++20 Coroutine Integration
1255
+
----------------------------------
1256
+
1257
+
LuaBridge3 provides first-class interoperability between C++20 coroutines and Lua coroutines, available when compiling with C++20 or later and Lua 5.2+ (requires `lua_yieldk`). The feature is guarded by `LUABRIDGE_HAS_CXX20_COROUTINES`, which is detected automatically and can be suppressed with `LUABRIDGE_DISABLE_CXX20_COROUTINES`.
1258
+
1259
+
> **Note:** C++20 coroutine integration is not supported on Lua 5.1, LuaJIT, or Luau (those targets lack a public `lua_yieldk` equivalent).
1260
+
1261
+
### 2.9.1 - CppCoroutine\<R\> — Generators callable from Lua
1262
+
1263
+
`luabridge::CppCoroutine<R>` is a coroutine return type that bridges C++20 coroutines with Lua's `coroutine.wrap` / `coroutine.resume` API. A function returning `CppCoroutine<R>` can use `co_yield` to suspend and pass a value back to Lua, and `co_return` to finish and return a final value.
1264
+
1265
+
Register via `Namespace::addCoroutine`:
1266
+
1267
+
```cpp
1268
+
luabridge::getGlobalNamespace(L)
1269
+
.addCoroutine("range", [](int from, int to) -> luabridge::CppCoroutine<int>
1270
+
{
1271
+
for (int i = from; i <= to; ++i)
1272
+
co_yield i;
1273
+
co_return -1; // sentinel value when the range is exhausted
1274
+
});
1275
+
```
1276
+
1277
+
From Lua, use `coroutine.wrap` to create a callable iterator:
1278
+
1279
+
```lua
1280
+
local gen = coroutine.wrap(range)
1281
+
local v = gen(1, 5) -- first call passes arguments; yields 1
1282
+
while v ~= -1 do
1283
+
print(v) -- 1, 2, 3, 4, 5
1284
+
v = gen() -- subsequent calls resume without arguments
1285
+
end
1286
+
```
1287
+
1288
+
`CppCoroutine<void>` is also supported for coroutines that produce no values:
An abandoned coroutine (one that goes out of scope in Lua without being fully consumed) is automatically cleaned up by the Lua garbage collector — no manual resource management is needed.
1299
+
1300
+
### 2.9.2 - Accepting Arguments
1301
+
1302
+
The factory lambda receives the Lua call arguments on first invocation. A `lua_State*` parameter, if present, must be the **first** parameter and receives the running Lua thread:
1303
+
1304
+
```cpp
1305
+
.addCoroutine("adder", [](int a, int b) -> luabridge::CppCoroutine<int>
1306
+
{
1307
+
co_yield a + b; // first resume yields the sum
1308
+
co_return a * b; // second resume returns the product
1309
+
});
1310
+
```
1311
+
1312
+
```lua
1313
+
localf=coroutine.wrap(adder)
1314
+
print(f(3, 4)) -- 7 (yield: 3+4)
1315
+
print(f()) -- 12 (return: 3*4)
1316
+
```
1317
+
1318
+
Multiple independent instances of the same coroutine factory can run concurrently — each call to `coroutine.wrap(name)` creates a separate C++ coroutine frame:
1319
+
1320
+
```lua
1321
+
locala=coroutine.wrap(adder)
1322
+
localb=coroutine.wrap(adder)
1323
+
a(1, 2) -- independent from b
1324
+
b(10, 20)
1325
+
```
1326
+
1327
+
### 2.9.3 - LuaCoroutine — Awaiting a Lua Thread from C++
1328
+
1329
+
`luabridge::LuaCoroutine` is an awaitable that can be used inside a `CppCoroutine` body to resume a child Lua thread synchronously. It runs the child thread to its first yield or return and gives back the status and the number of values the child left on its stack:
// Spawn a child Lua thread and anchor it in the registry so the GC
1335
+
// doesn't collect it while we hold a pointer to it.
1336
+
lua_State* child = lua_newthread(L);
1337
+
int ref = luaL_ref(L, LUA_REGISTRYINDEX); // pops thread from L's stack
1338
+
1339
+
lua_getglobal(child, "luaGenerator");
1340
+
1341
+
// Resume the child synchronously; suspends this C++ coroutine until done.
1342
+
auto [status, nresults] = co_await luabridge::LuaCoroutine{ child, L };
1343
+
1344
+
int value = (nresults > 0) ? static_cast<int>(lua_tointeger(child, -nresults)) : 0;
1345
+
1346
+
luaL_unref(L, LUA_REGISTRYINDEX, ref);
1347
+
co_return value;
1348
+
});
1349
+
```
1350
+
1351
+
`LuaCoroutine` always completes synchronously (no external event loop is required). The `status` field contains `LUA_YIELD` if the child yielded or `LUA_OK` if it returned normally.
1352
+
1353
+
### 2.9.4 - Limitations
1354
+
1355
+
***Lua version:** Requires Lua 5.2+ (`lua_yieldk`). Not supported on Lua 5.1, LuaJIT, or Luau.
1356
+
***C++ version:** Requires C++20 (`<coroutine>`). Non-coroutine features continue to work under C++17.
1357
+
***Multi-value yield:**`co_yield` sends exactly one value per suspension. Use `std::tuple` or a struct if multiple values are needed.
1358
+
***Thread safety:** Coroutine frames must be driven from a single OS thread.
1359
+
***Instance methods:**`addCoroutine` is available on `Namespace`; registering coroutine-returning member functions on `Class<T>` is not yet supported.
1360
+
1248
1361
3 - Passing Objects
1249
1362
===================
1250
1363
@@ -1965,6 +2078,30 @@ Override the default when you need fine-grained control:
LuaBridge3 automatically enables C++20 coroutine support when it detects a C++20 compiler (`__cplusplus >= 202002L` or MSVC `_HAS_CXX20`). The macro is set to `1` when the feature is active and `0` otherwise.
2087
+
2088
+
You can force the feature **off** by defining `LUABRIDGE_DISABLE_CXX20_COROUTINES` before including any LuaBridge header:
2089
+
2090
+
```cpp
2091
+
#define LUABRIDGE_DISABLE_CXX20_COROUTINES
2092
+
#include <LuaBridge/LuaBridge.h>
2093
+
```
2094
+
2095
+
You can also override the detection result explicitly:
2096
+
2097
+
```cpp
2098
+
#defineLUABRIDGE_HAS_CXX20_COROUTINES 0 // force off
2099
+
#define LUABRIDGE_HAS_CXX20_COROUTINES 1 // force on (must actually have C++20)
2100
+
#include <LuaBridge/LuaBridge.h>
2101
+
```
2102
+
2103
+
Attempting to use coroutine integration on Lua 5.1, LuaJIT, or Luau will emit a compile-time `#error` unless `LUABRIDGE_DISABLE_COROUTINE_INTEGRATION` is also defined.
2104
+
1968
2105
Appendix - API Reference
1969
2106
========================
1970
2107
@@ -2360,3 +2497,36 @@ TypeResult<T> get (lua_State* L, int index);
2360
2497
/// Checks if the Lua value at the index is convertible into the C++ value of the type T.
0 commit comments