Skip to content

Commit 27463a8

Browse files
Merge branch 'master' into master
2 parents ac8c38d + 3c0511f commit 27463a8

29 files changed

+760
-74
lines changed

.github/workflows/build.yml

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -310,14 +310,17 @@ jobs:
310310

311311
build-android:
312312
name: Build Android (on Linux)
313+
if: false #disabled due to continual failure
313314
runs-on: ubuntu-24.04
314315
steps:
315316
- uses: actions/checkout@v3
316317
- name: set up Java
317-
uses: actions/setup-java@v3
318+
uses: actions/setup-java@v4
318319
with:
319-
distribution: 'temurin'
320-
java-version: '11'
320+
distribution: temurin
321+
java-version: 17
322+
- name: set up Gradle
323+
uses: gradle/actions/setup-gradle@v4
321324
- name: set up flatc
322325
run: |
323326
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON .
@@ -398,11 +401,13 @@ jobs:
398401
# https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode
399402
- name: Set up Xcode version
400403
run: sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
401-
- uses: gradle/wrapper-validation-action@v1.0.5
402-
- uses: actions/setup-java@v3
404+
- name: set up Java
405+
uses: actions/setup-java@v4
403406
with:
404-
distribution: 'temurin'
405-
java-version: '11'
407+
distribution: temurin
408+
java-version: 17
409+
- name: set up Gradle
410+
uses: gradle/actions/setup-gradle@v4
406411
- name: Build flatc
407412
run: |
408413
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
@@ -414,15 +419,18 @@ jobs:
414419

415420
build-kotlin-linux:
416421
name: Build Kotlin Linux
422+
if: false #disabled due to continual failure
417423
runs-on: ubuntu-24.04
418424
steps:
419425
- name: Checkout
420426
uses: actions/checkout@v3
421-
- uses: actions/setup-java@v3
427+
- name: set up Java
428+
uses: actions/setup-java@v4
422429
with:
423-
distribution: 'temurin'
424-
java-version: '11'
425-
- uses: gradle/wrapper-validation-action@v1.0.5
430+
distribution: temurin
431+
java-version: 17
432+
- name: set up Gradle
433+
uses: gradle/actions/setup-gradle@v4
426434
- name: Build flatc
427435
run: |
428436
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
@@ -518,6 +526,8 @@ jobs:
518526
- uses: SwiftyLab/setup-swift@latest
519527
with:
520528
swift-version: '6.1'
529+
# To be removed when swiftylab fixes the CI
530+
visual-studio-components: Microsoft.VisualStudio.Component.Windows11SDK.22621
521531
- run: swift build
522532
- run: swift test
523533

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All major or breaking changes will be documented in this file, as well as any
44
new features that should be highlighted. Minor fixes or improvements are not
55
necessarily listed.
66

7+
## Unreleased
8+
9+
* flatc: `--grpc-callback-api` flag generates C++ gRPC Callback API server `CallbackService` skeletons AND client native callback/async stubs (unary + all streaming reactor forms) (opt-in, non-breaking, issue #8596).
10+
711
## [25.2.10] (February 10 2025)(https://github.com/google/flatbuffers/releases/tag/v25.2.10)
812

913
* Removed the old documentation pages. The new one is live at https://flatbuffers.dev

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ set(FlatBuffers_GRPCTest_SRCS
279279
tests/test_builder.cpp
280280
grpc/tests/grpctest.cpp
281281
grpc/tests/message_builder_test.cpp
282+
grpc/tests/grpctest_callback_compile.cpp
283+
grpc/tests/grpctest_callback_client_compile.cpp
282284
)
283285

284286
# TODO(dbaileychess): Figure out how this would now work. I posted a question on

go/grpc.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
package flatbuffers
22

3-
// Codec implements gRPC-go Codec which is used to encode and decode messages.
4-
var Codec = "flatbuffers"
3+
import "errors"
4+
5+
var (
6+
// Codec implements gRPC-go Codec which is used to encode and decode messages.
7+
Codec = "flatbuffers"
8+
9+
// ErrInsufficientData is returned when the data is too short to read the root UOffsetT.
10+
ErrInsufficientData = errors.New("insufficient data")
11+
12+
// ErrInvalidRootOffset is returned when the root UOffsetT is out of bounds.
13+
ErrInvalidRootOffset = errors.New("invalid root offset")
14+
)
515

616
// FlatbuffersCodec defines the interface gRPC uses to encode and decode messages. Note
717
// that implementations of this interface must be thread safe; a Codec's
@@ -15,7 +25,21 @@ func (FlatbuffersCodec) Marshal(v interface{}) ([]byte, error) {
1525

1626
// Unmarshal parses the wire format into v.
1727
func (FlatbuffersCodec) Unmarshal(data []byte, v interface{}) error {
18-
v.(flatbuffersInit).Init(data, GetUOffsetT(data))
28+
// Need at least 4 bytes to read the root table offset (UOffsetT).
29+
// Vtable soffset_t and metadata are read later during field access.
30+
if len(data) < SizeUOffsetT {
31+
return ErrInsufficientData
32+
}
33+
34+
off := GetUOffsetT(data)
35+
36+
// The root UOffsetT must be within the data buffer
37+
// Compare in the unsigned domain to avoid signedness pitfalls
38+
if off > UOffsetT(len(data)-SizeUOffsetT) {
39+
return ErrInvalidRootOffset
40+
}
41+
42+
v.(flatbuffersInit).Init(data, off)
1943
return nil
2044
}
2145

grpc/README.md

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
GRPC implementation and test
2-
============================
32

43
NOTE: files in `src/` are shared with the GRPC project, and maintained there
54
(any changes should be submitted to GRPC instead). These files are copied
@@ -39,4 +38,64 @@ For Bazel users:
3938

4039
```shell
4140
$bazel test tests/...
42-
```
41+
```
42+
43+
## C++ Callback API Generation
44+
45+
FlatBuffers gRPC C++ code generation now optionally supports the modern gRPC Callback API.
46+
47+
To enable generation of a `CallbackService` skeleton alongside the existing `Service` and async mixins, invoke `flatc` with both `--grpc` and `--grpc-callback-api`:
48+
49+
```shell
50+
flatc --cpp --grpc --grpc-callback-api your_service.fbs
51+
```
52+
53+
This adds (guarded by `#if defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)`) a class:
54+
55+
```cpp
56+
class YourService::CallbackService : public ::grpc::Service { /* reactor virtuals */ };
57+
```
58+
59+
Each RPC shape maps to the appropriate reactor return type:
60+
61+
- Unary -> `::grpc::ServerUnaryReactor*` Method(...)
62+
- Client streaming -> `::grpc::ServerReadReactor<Request>*`
63+
- Server streaming -> `::grpc::ServerWriteReactor<Response>*`
64+
- Bidi streaming -> `::grpc::ServerBidiReactor<Request, Response>*`
65+
66+
Default generated implementations return `nullptr`; override in your derived class and return a reactor instance you manage (see gRPC docs for lifecycle patterns).
67+
68+
If your gRPC library predates the stable callback API macro, the code inside the guard will be skipped (no breaking changes). Ensure you build against a recent gRPC (1.38+; verify current minimum in grpc repo) to use this feature.
69+
70+
### Client Callback Stubs
71+
72+
When `--grpc-callback-api` is supplied, the generated C++ client stub gains native callback / reactor based async methods in addition to the existing synchronous / generic async flavors, guarded by the same macro. For each RPC named `Foo`:
73+
74+
Unary:
75+
76+
```
77+
void async_Foo(::grpc::ClientContext*, const Request&, Response*, std::function<void(::grpc::Status)>);
78+
void async_Foo(::grpc::ClientContext*, const Request&, Response*, ::grpc::ClientUnaryReactor*);
79+
```
80+
81+
Client streaming:
82+
83+
```
84+
::grpc::ClientWriteReactor<Request>* async_Foo(::grpc::ClientContext*, Response*, ::grpc::ClientWriteReactor<Request>*);
85+
```
86+
87+
Server streaming:
88+
89+
```
90+
::grpc::ClientReadReactor<Response>* async_Foo(::grpc::ClientContext*, const Request&, ::grpc::ClientReadReactor<Response>*);
91+
```
92+
93+
Bidirectional streaming:
94+
95+
```
96+
::grpc::ClientBidiReactor<Request, Response>* async_Foo(::grpc::ClientContext*, ::grpc::ClientBidiReactor<Request, Response>*);
97+
```
98+
99+
These map directly onto the native gRPC callback API factories (e.g. `CallbackUnaryCall`, `ClientCallbackWriterFactory::Create`, etc.) and do not spawn threads. Override the appropriate reactor callbacks per gRPC's documentation to drive I/O.
100+
101+
If your build uses an older gRPC lacking the non-experimental macro, these symbols will not be emitted, preserving backwards compatibility.

0 commit comments

Comments
 (0)