@@ -173,3 +173,151 @@ func ExampleNewCallback_cdecl() {
173173
174174 // Output: 83
175175}
176+
177+ func TestNewCallbackInt32Packing (t * testing.T ) {
178+ var result int32
179+ cb := purego .NewCallback (func (a1 , a2 , a3 , a4 , a5 , a6 , a7 , a8 , a9 , a10 , a11 , a12 int32 ) int32 {
180+ result = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12
181+ return result
182+ })
183+
184+ var fn func (a1 , a2 , a3 , a4 , a5 , a6 , a7 , a8 , a9 , a10 , a11 , a12 int32 ) int32
185+ purego .RegisterFunc (& fn , cb )
186+
187+ got := fn (2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 )
188+ want := int32 (197 )
189+
190+ if got != want {
191+ t .Errorf ("callback returned %d, want %d" , got , want )
192+ }
193+ }
194+
195+ func TestNewCallbackMixedPacking (t * testing.T ) {
196+ var gotI32_1 , gotI32_2 int32
197+ var gotI64 int64
198+ cb := purego .NewCallback (func (r1 , r2 , r3 , r4 , r5 , r6 , r7 , r8 int64 , s1 int32 , s2 int64 , s3 int32 ) {
199+ gotI32_1 = s1
200+ gotI64 = s2
201+ gotI32_2 = s3
202+ })
203+
204+ var fn func (r1 , r2 , r3 , r4 , r5 , r6 , r7 , r8 int64 , s1 int32 , s2 int64 , s3 int32 )
205+ purego .RegisterFunc (& fn , cb )
206+
207+ fn (1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 100 , 200 , 300 )
208+
209+ if gotI32_1 != 100 || gotI64 != 200 || gotI32_2 != 300 {
210+ t .Errorf ("got (%d, %d, %d), want (100, 200, 300)" , gotI32_1 , gotI64 , gotI32_2 )
211+ }
212+ }
213+
214+ func TestNewCallbackSmallTypes (t * testing.T ) {
215+ var gotBool bool
216+ var gotI8 int8
217+ var gotU8 uint8
218+ var gotI16 int16
219+ var gotU16 uint16
220+ var gotI32 int32
221+ cb := purego .NewCallback (func (r1 , r2 , r3 , r4 , r5 , r6 , r7 , r8 int64 , b bool , i8 int8 , u8 uint8 , i16 int16 , u16 uint16 , i32 int32 ) {
222+ gotBool = b
223+ gotI8 = i8
224+ gotU8 = u8
225+ gotI16 = i16
226+ gotU16 = u16
227+ gotI32 = i32
228+ })
229+
230+ var fn func (r1 , r2 , r3 , r4 , r5 , r6 , r7 , r8 int64 , b bool , i8 int8 , u8 uint8 , i16 int16 , u16 uint16 , i32 int32 )
231+ purego .RegisterFunc (& fn , cb )
232+
233+ fn (1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , true , - 42 , 200 , - 1000 , 50000 , 123456 )
234+
235+ if ! gotBool || gotI8 != - 42 || gotU8 != 200 || gotI16 != - 1000 || gotU16 != 50000 || gotI32 != 123456 {
236+ t .Errorf ("got (bool=%v, i8=%d, u8=%d, i16=%d, u16=%d, i32=%d), want (true, -42, 200, -1000, 50000, 123456)" ,
237+ gotBool , gotI8 , gotU8 , gotI16 , gotU16 , gotI32 )
238+ }
239+ }
240+
241+ func TestCallbackFromC (t * testing.T ) {
242+ libFileName := filepath .Join (t .TempDir (), "libcbpackingtest.so" )
243+
244+ if err := buildSharedLib ("CC" , libFileName , filepath .Join ("testdata" , "libcbtest" , "callback_packing_test.c" )); err != nil {
245+ t .Fatal (err )
246+ }
247+ defer os .Remove (libFileName )
248+
249+ lib , err := purego .Dlopen (libFileName , purego .RTLD_NOW | purego .RTLD_GLOBAL )
250+ if err != nil {
251+ t .Fatalf ("Dlopen(%q) failed: %v" , libFileName , err )
252+ }
253+
254+ t .Run ("int32_packing" , func (t * testing.T ) {
255+ var result int32
256+ goCallback := func (a1 , a2 , a3 , a4 , a5 , a6 , a7 , a8 , a9 , a10 , a11 , a12 int32 ) int32 {
257+ result = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12
258+ return result
259+ }
260+
261+ var callCallbackInt32Packing func (uintptr ) int32
262+ purego .RegisterLibFunc (& callCallbackInt32Packing , lib , "callCallbackInt32Packing" )
263+
264+ cb := purego .NewCallback (goCallback )
265+ got := callCallbackInt32Packing (cb )
266+ want := int32 (197 ) // sum of primes: 2+3+5+7+11+13+17+19+23+29+31+37
267+
268+ if got != want {
269+ t .Errorf ("C called callback returned %d, want %d" , got , want )
270+ }
271+ if result != want {
272+ t .Errorf ("callback received wrong args, sum=%d, want %d" , result , want )
273+ }
274+ })
275+
276+ t .Run ("mixed_packing" , func (t * testing.T ) {
277+ var gotI32_1 , gotI32_2 int32
278+ var gotI64 int64
279+ goCallback := func (r1 , r2 , r3 , r4 , r5 , r6 , r7 , r8 int64 , s1 int32 , s2 int64 , s3 int32 ) {
280+ gotI32_1 = s1
281+ gotI64 = s2
282+ gotI32_2 = s3
283+ }
284+
285+ var callCallbackMixedPacking func (uintptr )
286+ purego .RegisterLibFunc (& callCallbackMixedPacking , lib , "callCallbackMixedPacking" )
287+
288+ cb := purego .NewCallback (goCallback )
289+ callCallbackMixedPacking (cb )
290+
291+ if gotI32_1 != 100 || gotI64 != 200 || gotI32_2 != 300 {
292+ t .Errorf ("callback received (%d, %d, %d), want (100, 200, 300)" , gotI32_1 , gotI64 , gotI32_2 )
293+ }
294+ })
295+
296+ t .Run ("small_types" , func (t * testing.T ) {
297+ var gotBool bool
298+ var gotI8 int8
299+ var gotU8 uint8
300+ var gotI16 int16
301+ var gotU16 uint16
302+ var gotI32 int32
303+ goCallback := func (r1 , r2 , r3 , r4 , r5 , r6 , r7 , r8 int64 , b bool , i8 int8 , u8 uint8 , i16 int16 , u16 uint16 , i32 int32 ) {
304+ gotBool = b
305+ gotI8 = i8
306+ gotU8 = u8
307+ gotI16 = i16
308+ gotU16 = u16
309+ gotI32 = i32
310+ }
311+
312+ var callCallbackSmallTypes func (uintptr )
313+ purego .RegisterLibFunc (& callCallbackSmallTypes , lib , "callCallbackSmallTypes" )
314+
315+ cb := purego .NewCallback (goCallback )
316+ callCallbackSmallTypes (cb )
317+
318+ if ! gotBool || gotI8 != - 42 || gotU8 != 200 || gotI16 != - 1000 || gotU16 != 50000 || gotI32 != 123456 {
319+ t .Errorf ("callback received (bool=%v, i8=%d, u8=%d, i16=%d, u16=%d, i32=%d), want (true, -42, 200, -1000, 50000, 123456)" ,
320+ gotBool , gotI8 , gotU8 , gotI16 , gotU16 , gotI32 )
321+ }
322+ })
323+ }
0 commit comments