Skip to content

purego: fix returning a C function pointer as a Go func - #500

Open
NotAFlightRisk wants to merge 2 commits into
ebitengine:mainfrom
NotAFlightRisk:fix-func-return-type
Open

purego: fix returning a C function pointer as a Go func#500
NotAFlightRisk wants to merge 2 commits into
ebitengine:mainfrom
NotAFlightRisk:fix-func-return-type

Conversation

@NotAFlightRisk

@NotAFlightRisk NotAFlightRisk commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

What issue is this addressing?

#501

What type of issue is this addressing?

bug

What this PR does | solves

The RegisterFunc type table has func <=> C function in it, but that only holds in the argument direction. Declare a C function as returning a func, and calling it panics:

panic: reflect.MakeFunc: value of type *func(int32, int32) int32 is not assignable to type func(int32, int32) int32

Registering is fine, it's the call that goes, and it goes for every signature. Every other case in that return switch leaves the result as the declared type. The reflect.Func case swapped in a *func, registered into that, and handed the pointer back to MakeFunc, which wont take it.

If the C function returns NULL the inner RegisterFunc still panics purego: cfn is nil. Left that alone, since whether it should hand you a nil Go func instead looked like your call rather than a bug.

Test is a block in TestABI plus a return_func_ptr helper in abi_test.c, and it fails on main with teh panic above. Been broken since #49 back in 2022, which is probably why nobody's hit it: you'd normally take the pointer back as a uintptr and register it youself, and nothing in the repo declares a func return.

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

Fixes an issue in purego.RegisterFunc where a C function that returns a function pointer would be wrapped as a *func(...)... and then returned from reflect.MakeFunc, causing a panic due to a type mismatch. This aligns the return-path behavior for reflect.Func with the other return-kind cases (i.e., returning the declared Go type, not a pointer to it).

Changes:

  • Fix reflect.Func return handling so the returned value remains a Go func (not *func) while still allowing RegisterFunc to populate it.
  • Add an ABI test case for a C function that returns a function pointer, and validate calling the returned function from Go.
  • Add a C test helper that returns a function pointer (return_func_ptr).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
func.go Fixes the reflect.Func return-kind path to register into the address of the func value while returning the correctly-typed func.
func_test.go Adds a regression test that calls a C function returning a function pointer and then invokes the returned function from Go.
testdata/abitest/abi_test.c Adds return_func_ptr and its target function to supply a function pointer return value for the ABI test.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread func.go Outdated
@TotallyGamerJet

Copy link
Copy Markdown
Collaborator

None. Happy to file one if you'd rather have it tracked.

Yes please create one

@hajimehoshi hajimehoshi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@TotallyGamerJet PTAL

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.

4 participants