diff --git a/func.go b/func.go index 57afd93e..005813be 100644 --- a/func.go +++ b/func.go @@ -409,8 +409,9 @@ func RegisterFunc(fptr any, cfn uintptr) { v = reflect.NewAt(outType, unsafe.Pointer(&a1)).Elem() case reflect.Func: // wrap this C function in a nicely typed Go function - v = reflect.New(outType) - RegisterFunc(v.Interface(), syscall.a1) + if syscall.a1 != 0 { + RegisterFunc(v.Addr().Interface(), syscall.a1) + } case reflect.String: v.SetString(strings.GoString(syscall.a1)) case reflect.Float32: diff --git a/func_test.go b/func_test.go index f5190714..fb853276 100644 --- a/func_test.go +++ b/func_test.go @@ -239,6 +239,24 @@ func TestABI(t *testing.T) { t.Fatalf("%s: got %q, want %q", cName, res, want) } } + { + const cName = "return_func_ptr" + var fn func() func(a, b int32) int32 + purego.RegisterLibFunc(&fn, lib, cName) + add := fn() + const expect = 5 + if res := add(2, 3); res != expect { + t.Fatalf("%s: got %d, want %d", cName, res, expect) + } + } + { + const cName = "return_null_func_ptr" + var fn func() func(a, b int32) int32 + purego.RegisterLibFunc(&fn, lib, cName) + if fn() != nil { + t.Fatalf("%s: got a non-nil func, want nil", cName) + } + } } func TestABI_ArgumentPassing(t *testing.T) { diff --git a/testdata/abitest/abi_test.c b/testdata/abitest/abi_test.c index c129d26d..86eeca67 100644 --- a/testdata/abitest/abi_test.c +++ b/testdata/abitest/abi_test.c @@ -197,3 +197,17 @@ double arm_float64_unaligned_on_stack(uintptr_t a1, uintptr_t a2, uintptr_t a3, return (double)a1 * 1 + (double)a2 * 2 + (double)a3 * 3 + (double)a4 * 4 + (double)a5 * 5 + a6; } + +typedef int32_t (*AddFunc)(int32_t, int32_t); + +int32_t returned_add(int32_t a, int32_t b) { + return a + b; +} + +AddFunc return_func_ptr(void) { + return returned_add; +} + +AddFunc return_null_func_ptr(void) { + return NULL; +}