Skip to content

purego: support structs on Android and iOS#467

Merged
hajimehoshi merged 1 commit into
ebitengine:mainfrom
hajimehoshi:claude/kind-spence-5479dd
Jun 23, 2026
Merged

purego: support structs on Android and iOS#467
hajimehoshi merged 1 commit into
ebitengine:mainfrom
hajimehoshi:claude/kind-spence-5479dd

Conversation

@hajimehoshi

Copy link
Copy Markdown
Member

What issue is this addressing?

Closes #466

What type of issue is this addressing?

feature

What this PR does | solves

Enables passing and returning C structs by value on Android and iOS for
amd64 and arm64, in both RegisterFunc/RegisterLibFunc calls and NewCallback
callbacks — matching the support already available on macOS, Linux, and Windows
(#236, #237).

Why it works

The struct-marshalling code was already compiled into the iOS/Android builds and
only gated off by runtime.GOOS string checks. Their ABIs are identical to
platforms that already work:

  • iOS arm64 == macOS arm64 (Apple ABI); the iOS simulator (amd64) is System V.
  • Android amd64 == System V; Android arm64 == standard AAPCS64.

So this routes GOOS=ios through the Darwin path via a new isDarwin helper,
treats GOOS=android like Linux, opens the ensureStructSupported gate to
ios/android, adds them to the getCallbackStruct callback switches, and extends
the Darwin ARM64 stack-argument reads in the callback path to iOS.

Tests / CI

Adds an Android emulator CI job (amd64 and arm64) that runs the test suite.
Because the emulator has no C toolchain, the test libraries are cross-compiled on
the host with the NDK and loaded via a new PUREGO_TEST_PREBUILT_LIBDIR env var
instead of being compiled at run time. getSystemLibrary also learns Android's
libc (and iOS, for a future job).

Reviewer notes

  • I could not run the Android emulator job locally (no emulator/NDK in my
    environment), so it may need a CI iteration to settle image/arch specifics —
    notably the arm64-v8a image under full emulation on the x86_64 runner, and
    dlopen("libc.so") for the adb-shell user. The harness change itself is
    verified on the host: the full suite passes through PUREGO_TEST_PREBUILT_LIBDIR.
  • An iOS Simulator job is left as a TODO in the workflow (lower marginal value,
    since the iOS arm64 ABI matches macOS arm64, which the macOS runner already
    exercises).

Authored by Claude (Claude Code) on behalf of @hajimehoshi.

Copilot AI review requested due to automatic review settings June 20, 2026 05:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends PureGo’s struct-by-value ABI support to Android and iOS (amd64/arm64), aligning the runtime GOOS gating with ABIs already supported on macOS/Linux/Windows, and adds CI coverage to exercise the Android paths.

Changes:

  • Allow struct arguments/returns on GOOS=android and GOOS=ios by widening ensureStructSupported, routing iOS through a new isDarwin() helper, and treating Android like Linux in callback struct decoding.
  • Update callback stack-reading/struct marshalling logic to apply the Darwin ARM64 packing rules on iOS as well.
  • Add an Android emulator workflow job and a test harness path for loading prebuilt shared libraries via PUREGO_TEST_PREBUILT_LIBDIR; teach tests to locate Android libc.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
syscall_unix.go Uses isDarwin() to apply Darwin ARM64 stack unpacking on iOS as well as macOS.
struct_arm64.go Generalizes Darwin-vs-Linux ARM64 struct handling to include iOS/Android; expands callback struct support switches.
struct_amd64.go Expands callback struct support switches to include iOS/Android on amd64.
README.md Updates platform notes to reflect struct-by-value support on Android/iOS amd64/arm64.
func.go Opens struct support gate for android/ios and introduces isDarwin() helper used across ABI logic.
func_test.go Adds Android/iOS system library resolution and supports prebuilt test shared libraries via env var.
.github/workflows/test.yml Adds an Android emulator CI job (amd64/arm64) that runs the test binary with prebuilt libraries.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread struct_arm64.go Outdated
Comment thread struct_arm64.go Outdated
@hajimehoshi hajimehoshi force-pushed the claude/kind-spence-5479dd branch 4 times, most recently from d6ee7a4 to 9fae168 Compare June 20, 2026 06:55
@hajimehoshi hajimehoshi reopened this Jun 20, 2026
@hajimehoshi

Copy link
Copy Markdown
Member Author

@TotallyGamerJet Please take a look, thanks

Comment thread .github/workflows/test.yml
Comment thread README.md
Comment thread func.go Outdated
Enable passing and returning C structs by value on Android and iOS for
amd64 and arm64, in both RegisterFunc calls and NewCallback callbacks.

The struct-marshalling code already compiled into these builds and was
only gated off by runtime.GOOS string checks. iOS shares the Apple ABI
with macOS and Android shares the standard ABI with Linux, so route
GOOS=ios through the Darwin path via a new isDarwin helper and treat
GOOS=android like Linux. Open the ensureStructSupported gate, add ios
and android to the getCallbackStruct callback switches, and extend the
Darwin ARM64 stack-argument reads in the callback path to iOS.

Add an Android emulator CI job (amd64 and arm64) that runs the test
suite. Because the emulator has no C toolchain, the test libraries are
cross-compiled on the host with the NDK and loaded via the new
PUREGO_TEST_PREBUILT_LIBDIR instead of being compiled at run time.

Closes ebitengine#466

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@hajimehoshi hajimehoshi force-pushed the claude/kind-spence-5479dd branch from 9fae168 to f49be2a Compare June 22, 2026 17:08

@TotallyGamerJet TotallyGamerJet left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hajimehoshi hajimehoshi merged commit 576826c into ebitengine:main Jun 23, 2026
44 checks passed
@hajimehoshi hajimehoshi deleted the claude/kind-spence-5479dd branch June 23, 2026 02:57
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.

Struct support on Android and iOS

3 participants