From f14915e6454733d41f3a5671beed61e2886f3767 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 19:19:11 +0000 Subject: [PATCH] feat(cgo): map Call non-zero returns to errno Co-Authored-By: Virgil --- call_test.go | 2 ++ string_conversion.go | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/call_test.go b/call_test.go index 5305508..e7284c9 100644 --- a/call_test.go +++ b/call_test.go @@ -69,6 +69,8 @@ func TestCallWrapsZeroAndNonZeroReturns(t *testing.T) { if err := Call(callFailureFunction()); err == nil { t.Fatalf("expected error, got nil") + } else if !errors.Is(err, syscall.Errno(13)) { + t.Fatalf("expected errno error for return code 13, got %T %v", err, err) } } diff --git a/string_conversion.go b/string_conversion.go index 5a556d5..f276b48 100644 --- a/string_conversion.go +++ b/string_conversion.go @@ -43,7 +43,6 @@ int cgo_call_6(uintptr_t fn, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t import "C" import ( - "fmt" "strconv" "syscall" "unsafe" @@ -89,7 +88,7 @@ func cIntBitSize() int { return int(unsafe.Sizeof(C.int(0)) * 8) } -// Call invokes a C function pointer and maps a non-zero return into a Go error. +// Call invokes a C function pointer and maps a non-zero return into a Go error using errno mapping. // // err := cgo.Call(unsafe.Pointer(C.some_function), cgo.SizeT(len(data))) // err == nil indicates success. @@ -98,18 +97,18 @@ func Call(function unsafe.Pointer, args ...interface{}) error { panic("cgo.Call: function pointer is nil") } - var result uintptr + var result C.int target := uintptr(function) switch len(args) { case 0: - result = uintptr(C.cgo_call_0(C.uintptr_t(target))) + result = C.cgo_call_0(C.uintptr_t(target)) case 1: a0, ok := toSyscallArg(args[0]) if !ok { panic("cgo.Call: unsupported argument type") } - result = uintptr(C.cgo_call_1(C.uintptr_t(target), C.uintptr_t(a0))) + result = C.cgo_call_1(C.uintptr_t(target), C.uintptr_t(a0)) case 2: a0, ok := toSyscallArg(args[0]) if !ok { @@ -119,7 +118,7 @@ func Call(function unsafe.Pointer, args ...interface{}) error { if !ok { panic("cgo.Call: unsupported argument type") } - result = uintptr(C.cgo_call_2(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1))) + result = C.cgo_call_2(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1)) case 3: a0, ok := toSyscallArg(args[0]) if !ok { @@ -133,7 +132,7 @@ func Call(function unsafe.Pointer, args ...interface{}) error { if !ok { panic("cgo.Call: unsupported argument type") } - result = uintptr(C.cgo_call_3(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1), C.uintptr_t(a2))) + result = C.cgo_call_3(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1), C.uintptr_t(a2)) case 4: a0, ok := toSyscallArg(args[0]) if !ok { @@ -151,7 +150,7 @@ func Call(function unsafe.Pointer, args ...interface{}) error { if !ok { panic("cgo.Call: unsupported argument type") } - result = uintptr(C.cgo_call_4(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3))) + result = C.cgo_call_4(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3)) case 5: a0, ok := toSyscallArg(args[0]) if !ok { @@ -173,7 +172,7 @@ func Call(function unsafe.Pointer, args ...interface{}) error { if !ok { panic("cgo.Call: unsupported argument type") } - result = uintptr(C.cgo_call_5(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3), C.uintptr_t(a4))) + result = C.cgo_call_5(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3), C.uintptr_t(a4)) case 6: a0, ok := toSyscallArg(args[0]) if !ok { @@ -199,13 +198,13 @@ func Call(function unsafe.Pointer, args ...interface{}) error { if !ok { panic("cgo.Call: unsupported argument type") } - result = uintptr(C.cgo_call_6(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3), C.uintptr_t(a4), C.uintptr_t(a5))) + result = C.cgo_call_6(C.uintptr_t(target), C.uintptr_t(a0), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3), C.uintptr_t(a4), C.uintptr_t(a5)) default: panic("cgo.Call: unsupported argument count: max 6") } if result != 0 { - return fmt.Errorf("cgo.Call: return code %d", int(result)) + return Errno(result) } return nil }