Skip to content

JNI: support consumers with C++ interoperability enabled - #927

Open
NakaokaRei wants to merge 2 commits into
swiftlang:mainfrom
NakaokaRei:fix/jni-cxx-interoperability
Open

NakaokaRei wants to merge 2 commits into
swiftlang:mainfrom
NakaokaRei:fix/jni-cxx-interoperability

Conversation

@NakaokaRei

Copy link
Copy Markdown
Contributor

Fixes #391. Follow-up to #463.

Problem

Enabling .interoperabilityMode(.Cxx) in a consumer changes how JNI headers are imported. In particular, Android exposes different JNIEnv and reference types in C++ mode, while SwiftJava's runtime uses their C definitions. Generated JNI entry points and calls then fail with type mismatches.

Solution

  • Generate entry points using JNIEnvironment and runtime-owned JNITypes aliases. Add typed JNI function-table accessors and an object-value factory to preserve C signatures in C++ consumers, without unsafeBitCast.
  • Update generator and macro test expectations.
  • Enable C++ mode only on the JavaKit and JNI sample consumer targets via CXX_INTEROP=1. Following the feedback on fix: .interoperabilityMode(.Cxx) build issue #463, reuse existing stable Swift 6.3 CI jobs on Linux/macOS and one Android configuration, retaining verbose output. Rerun Gradle tests across configurations and avoid stale toolchain daemons.

Testing

Locally verified before rebasing onto current main (the patch is unchanged):

  • 820 package tests; JavaKit and JNI samples in normal and C++ modes on macOS and Linux ARM64.
  • Android JNI sample build; hello-cpp-swift built and ran on an emulator with C++ interoperability enabled and extern "C" removed.
  • Scoped act formatting, ShellCheck, and sample checks using local workflow adaptations. The full unmodified workflow and Linux AMD64 execution were not verified locally; GitHub CI remains to be confirmed.

Preserve the runtime's C JNI types in generated entry points and calls.
Expose typed JNI interface getters and an object-value factory so Android
consumers do not reimport JNI signatures using the NDK's C++ wrappers.
Update generator and macro expectations for the preserved types.

Allow the JavaKit and JNI extraction samples to opt into C++ interoperability
on consumer targets only. Exercise this mode in existing stable Swift CI
jobs, including one Android configuration, and rerun Gradle tests across
configurations without reusing a daemon from another Swift toolchain.

Validation: 820 package tests; normal and C++ sample tests on macOS and
Linux ARM64; Android JNI sample build; hello-cpp-swift emulator execution.
Scoped act format, shell, and sample checks passed; the full GitHub Actions
workflow and Linux AMD64 execution remain unverified.
@NakaokaRei
NakaokaRei requested a review from ktoso as a code owner October 5, 2026 10:51
Preserve main's Java exception conversion while keeping C-compatible JNI
calls in generated async thunks. Use JNITypes.jthrowable for the new error
conformances and update closure expectations added since the original fix.

Validated with 839 Swift tests and 270 macOS C++ JNI sample tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JavaKitSampleApp can't build with .interoperabilityMode(.Cxx) in swiftSettings

1 participant