From b5e288510f845c9038f194f012bb56aa3beff762 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 19:23:54 +0000 Subject: [PATCH] feat(cgo): extend Call for up to 16 arguments Co-Authored-By: Virgil --- call_test.go | 34 +++++- call_test_support.go | 64 +++++++++++ string_conversion.go | 263 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 359 insertions(+), 2 deletions(-) diff --git a/call_test.go b/call_test.go index 8f621ba..12dc38a 100644 --- a/call_test.go +++ b/call_test.go @@ -82,10 +82,42 @@ func TestCallRejectsUnsupportedInputs(t *testing.T) { }) assertPanics(t, "unsupported argument count", func() { - _ = Call(callFailureFunction(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13) + _ = Call(callFailureFunction(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17) }) } +func TestCallSupportsThirteenArguments(t *testing.T) { + t.Parallel() + + if err := Call(callThirteenArgumentFunction(), 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22); err != nil { + t.Fatalf("expected success, got error: %v", err) + } +} + +func TestCallSupportsFourteenArguments(t *testing.T) { + t.Parallel() + + if err := Call(callFourteenArgumentFunction(), 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23); err != nil { + t.Fatalf("expected success, got error: %v", err) + } +} + +func TestCallSupportsFifteenArguments(t *testing.T) { + t.Parallel() + + if err := Call(callFifteenArgumentFunction(), 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24); err != nil { + t.Fatalf("expected success, got error: %v", err) + } +} + +func TestCallSupportsSixteenArguments(t *testing.T) { + t.Parallel() + + if err := Call(callSixteenArgumentFunction(), 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25); err != nil { + t.Fatalf("expected success, got error: %v", err) + } +} + func TestCallSupportsSixArguments(t *testing.T) { t.Parallel() diff --git a/call_test_support.go b/call_test_support.go index 44119e8..44e2fb1 100644 --- a/call_test_support.go +++ b/call_test_support.go @@ -43,6 +43,34 @@ int call_nine_args(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintp return 13; } +int call_thirteen_args(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12) { + if (a0 == 10 && a1 == 11 && a2 == 12 && a3 == 13 && a4 == 14 && a5 == 15 && a6 == 16 && a7 == 17 && a8 == 18 && a9 == 19 && a10 == 20 && a11 == 21 && a12 == 22) { + return 0; + } + return 13; +} + +int call_fourteen_args(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13) { + if (a0 == 10 && a1 == 11 && a2 == 12 && a3 == 13 && a4 == 14 && a5 == 15 && a6 == 16 && a7 == 17 && a8 == 18 && a9 == 19 && a10 == 20 && a11 == 21 && a12 == 22 && a13 == 23) { + return 0; + } + return 13; +} + +int call_fifteen_args(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14) { + if (a0 == 10 && a1 == 11 && a2 == 12 && a3 == 13 && a4 == 14 && a5 == 15 && a6 == 16 && a7 == 17 && a8 == 18 && a9 == 19 && a10 == 20 && a11 == 21 && a12 == 22 && a13 == 23 && a14 == 24) { + return 0; + } + return 13; +} + +int call_sixteen_args(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15) { + if (a0 == 10 && a1 == 11 && a2 == 12 && a3 == 13 && a4 == 14 && a5 == 15 && a6 == 16 && a7 == 17 && a8 == 18 && a9 == 19 && a10 == 20 && a11 == 21 && a12 == 22 && a13 == 23 && a14 == 24 && a15 == 25) { + return 0; + } + return 13; +} + int call_buffer_argument(uintptr_t value) { return value == 0 ? 13 : 0; } @@ -71,6 +99,22 @@ uintptr_t call_nine_args_ptr(void) { return (uintptr_t)&call_nine_args; } +uintptr_t call_thirteen_args_ptr(void) { + return (uintptr_t)&call_thirteen_args; +} + +uintptr_t call_fourteen_args_ptr(void) { + return (uintptr_t)&call_fourteen_args; +} + +uintptr_t call_fifteen_args_ptr(void) { + return (uintptr_t)&call_fifteen_args; +} + +uintptr_t call_sixteen_args_ptr(void) { + return (uintptr_t)&call_sixteen_args; +} + uintptr_t call_buffer_argument_ptr(void) { return (uintptr_t)&call_buffer_argument; } @@ -110,6 +154,26 @@ func callNineArgumentFunction() unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&function)) } +func callThirteenArgumentFunction() unsafe.Pointer { + function := C.call_thirteen_args_ptr() + return *(*unsafe.Pointer)(unsafe.Pointer(&function)) +} + +func callFourteenArgumentFunction() unsafe.Pointer { + function := C.call_fourteen_args_ptr() + return *(*unsafe.Pointer)(unsafe.Pointer(&function)) +} + +func callFifteenArgumentFunction() unsafe.Pointer { + function := C.call_fifteen_args_ptr() + return *(*unsafe.Pointer)(unsafe.Pointer(&function)) +} + +func callSixteenArgumentFunction() unsafe.Pointer { + function := C.call_sixteen_args_ptr() + return *(*unsafe.Pointer)(unsafe.Pointer(&function)) +} + func callBufferArgumentFunction() unsafe.Pointer { function := C.call_buffer_argument_ptr() return *(*unsafe.Pointer)(unsafe.Pointer(&function)) diff --git a/string_conversion.go b/string_conversion.go index 363a77e..f73b2ee 100644 --- a/string_conversion.go +++ b/string_conversion.go @@ -17,6 +17,10 @@ typedef int (*cgo_call_int_fn9_t)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, ui typedef int (*cgo_call_int_fn10_t)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); typedef int (*cgo_call_int_fn11_t)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); typedef int (*cgo_call_int_fn12_t)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +typedef int (*cgo_call_int_fn13_t)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +typedef int (*cgo_call_int_fn14_t)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +typedef int (*cgo_call_int_fn15_t)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +typedef int (*cgo_call_int_fn16_t)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); int cgo_call_0(uintptr_t fn) { return ((cgo_call_int_fn0_t)fn)(); @@ -69,6 +73,23 @@ int cgo_call_11(uintptr_t fn, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_ int cgo_call_12(uintptr_t fn, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11) { return ((cgo_call_int_fn12_t)fn)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + +int cgo_call_13(uintptr_t fn, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12) { + return ((cgo_call_int_fn13_t)fn)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); +} + +int cgo_call_14(uintptr_t fn, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13) { + return ((cgo_call_int_fn14_t)fn)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); +} + +int cgo_call_15(uintptr_t fn, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14) { + return ((cgo_call_int_fn15_t)fn)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); +} + +int cgo_call_16(uintptr_t fn, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15) { + return ((cgo_call_int_fn16_t)fn)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); +} + */ import "C" @@ -469,8 +490,248 @@ func Call(function unsafe.Pointer, args ...interface{}) error { panic("cgo.Call: unsupported argument type") } result = C.cgo_call_12(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), C.uintptr_t(a6), C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11)) + case 13: + a0, ok := toSyscallArg(args[0]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a1, ok := toSyscallArg(args[1]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a2, ok := toSyscallArg(args[2]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a3, ok := toSyscallArg(args[3]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a4, ok := toSyscallArg(args[4]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a5, ok := toSyscallArg(args[5]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a6, ok := toSyscallArg(args[6]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a7, ok := toSyscallArg(args[7]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a8, ok := toSyscallArg(args[8]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a9, ok := toSyscallArg(args[9]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a10, ok := toSyscallArg(args[10]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a11, ok := toSyscallArg(args[11]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a12, ok := toSyscallArg(args[12]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + result = C.cgo_call_13(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), C.uintptr_t(a6), C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12)) + case 14: + a0, ok := toSyscallArg(args[0]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a1, ok := toSyscallArg(args[1]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a2, ok := toSyscallArg(args[2]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a3, ok := toSyscallArg(args[3]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a4, ok := toSyscallArg(args[4]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a5, ok := toSyscallArg(args[5]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a6, ok := toSyscallArg(args[6]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a7, ok := toSyscallArg(args[7]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a8, ok := toSyscallArg(args[8]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a9, ok := toSyscallArg(args[9]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a10, ok := toSyscallArg(args[10]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a11, ok := toSyscallArg(args[11]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a12, ok := toSyscallArg(args[12]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a13, ok := toSyscallArg(args[13]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + result = C.cgo_call_14(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), C.uintptr_t(a6), C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12), C.uintptr_t(a13)) + case 15: + a0, ok := toSyscallArg(args[0]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a1, ok := toSyscallArg(args[1]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a2, ok := toSyscallArg(args[2]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a3, ok := toSyscallArg(args[3]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a4, ok := toSyscallArg(args[4]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a5, ok := toSyscallArg(args[5]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a6, ok := toSyscallArg(args[6]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a7, ok := toSyscallArg(args[7]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a8, ok := toSyscallArg(args[8]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a9, ok := toSyscallArg(args[9]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a10, ok := toSyscallArg(args[10]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a11, ok := toSyscallArg(args[11]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a12, ok := toSyscallArg(args[12]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a13, ok := toSyscallArg(args[13]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a14, ok := toSyscallArg(args[14]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + result = C.cgo_call_15(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), C.uintptr_t(a6), C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12), C.uintptr_t(a13), C.uintptr_t(a14)) + case 16: + a0, ok := toSyscallArg(args[0]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a1, ok := toSyscallArg(args[1]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a2, ok := toSyscallArg(args[2]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a3, ok := toSyscallArg(args[3]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a4, ok := toSyscallArg(args[4]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a5, ok := toSyscallArg(args[5]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a6, ok := toSyscallArg(args[6]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a7, ok := toSyscallArg(args[7]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a8, ok := toSyscallArg(args[8]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a9, ok := toSyscallArg(args[9]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a10, ok := toSyscallArg(args[10]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a11, ok := toSyscallArg(args[11]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a12, ok := toSyscallArg(args[12]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a13, ok := toSyscallArg(args[13]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a14, ok := toSyscallArg(args[14]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + a15, ok := toSyscallArg(args[15]) + if !ok { + panic("cgo.Call: unsupported argument type") + } + result = C.cgo_call_16(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), C.uintptr_t(a6), C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12), C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15)) default: - panic("cgo.Call: unsupported argument count: max 12") + panic("cgo.Call: unsupported argument count: max 16") } if result != 0 {