ffi 1.17.1 → 1.17.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +33 -0
  4. data/Gemfile +8 -3
  5. data/README.md +1 -0
  6. data/Rakefile +7 -4
  7. data/Steepfile +8 -0
  8. data/ext/ffi_c/DynamicLibrary.c +1 -1
  9. data/ext/ffi_c/Function.c +2 -0
  10. data/ext/ffi_c/MethodHandle.c +4 -2
  11. data/ext/ffi_c/libffi/.ci/Containerfile.ppc64le +12 -0
  12. data/ext/ffi_c/libffi/.ci/build.sh +38 -33
  13. data/ext/ffi_c/libffi/.ci/install.sh +46 -50
  14. data/ext/ffi_c/libffi/.ci/site.exp +6 -0
  15. data/ext/ffi_c/libffi/.gail-labels +44 -0
  16. data/ext/ffi_c/libffi/.github/workflows/build.yml +212 -333
  17. data/ext/ffi_c/libffi/.github/workflows/emscripten.yml +101 -58
  18. data/ext/ffi_c/libffi/.github/workflows/label-new-issue.yaml +15 -0
  19. data/ext/ffi_c/libffi/.github/workflows/tarball.yml +55 -0
  20. data/ext/ffi_c/libffi/LICENSE +1 -1
  21. data/ext/ffi_c/libffi/Makefile.am +20 -15
  22. data/ext/ffi_c/libffi/Makefile.in +41 -54
  23. data/ext/ffi_c/libffi/README.md +40 -4
  24. data/ext/ffi_c/libffi/acinclude.m4 +6 -0
  25. data/ext/ffi_c/libffi/config.guess +80 -22
  26. data/ext/ffi_c/libffi/config.sub +161 -80
  27. data/ext/ffi_c/libffi/configure +1058 -1372
  28. data/ext/ffi_c/libffi/configure.ac +28 -14
  29. data/ext/ffi_c/libffi/configure.host +6 -6
  30. data/ext/ffi_c/libffi/doc/Makefile.in +4 -0
  31. data/ext/ffi_c/libffi/doc/libffi.texi +27 -4
  32. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  33. data/ext/ffi_c/libffi/fficonfig.h.in +9 -9
  34. data/ext/ffi_c/libffi/generate-darwin-source-and-headers.py +1 -28
  35. data/ext/ffi_c/libffi/include/Makefile.in +4 -0
  36. data/ext/ffi_c/libffi/include/ffi.h.in +19 -1
  37. data/ext/ffi_c/libffi/include/ffi_cfi.h +2 -0
  38. data/ext/ffi_c/libffi/include/ffi_common.h +17 -0
  39. data/ext/ffi_c/libffi/libffi.map.in +13 -1
  40. data/ext/ffi_c/libffi/libtool-version +1 -1
  41. data/ext/ffi_c/libffi/m4/asmcfi.m4 +28 -11
  42. data/ext/ffi_c/libffi/m4/ax_check_compile_flag.m4 +13 -3
  43. data/ext/ffi_c/libffi/man/Makefile.in +4 -0
  44. data/ext/ffi_c/libffi/src/aarch64/ffi.c +7 -4
  45. data/ext/ffi_c/libffi/src/aarch64/ffitarget.h +2 -2
  46. data/ext/ffi_c/libffi/src/aarch64/internal.h +63 -17
  47. data/ext/ffi_c/libffi/src/aarch64/sysv.S +22 -12
  48. data/ext/ffi_c/libffi/src/arc/arcompact.S +2 -2
  49. data/ext/ffi_c/libffi/src/arc/ffi.c +6 -2
  50. data/ext/ffi_c/libffi/src/arm/sysv.S +1 -1
  51. data/ext/ffi_c/libffi/src/closures.c +3 -3
  52. data/ext/ffi_c/libffi/src/dlmalloc.c +1 -0
  53. data/ext/ffi_c/libffi/src/mips/ffitarget.h +2 -4
  54. data/ext/ffi_c/libffi/src/mips/n32.S +4 -0
  55. data/ext/ffi_c/libffi/src/mips/o32.S +4 -0
  56. data/ext/ffi_c/libffi/src/or1k/ffi.c +2 -2
  57. data/ext/ffi_c/libffi/src/pa/linux.S +4 -0
  58. data/ext/ffi_c/libffi/src/powerpc/ffi.c +19 -0
  59. data/ext/ffi_c/libffi/src/powerpc/ffi_linux64.c +26 -19
  60. data/ext/ffi_c/libffi/src/powerpc/ffi_sysv.c +26 -16
  61. data/ext/ffi_c/libffi/src/powerpc/internal.h +10 -0
  62. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +47 -0
  63. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +24 -0
  64. data/ext/ffi_c/libffi/src/prep_cif.c +1 -4
  65. data/ext/ffi_c/libffi/src/riscv/ffi.c +39 -16
  66. data/ext/ffi_c/libffi/src/riscv/internal.h +7 -0
  67. data/ext/ffi_c/libffi/src/riscv/sysv.S +24 -0
  68. data/ext/ffi_c/libffi/src/s390/ffi.c +28 -1
  69. data/ext/ffi_c/libffi/src/s390/internal.h +11 -0
  70. data/ext/ffi_c/libffi/src/s390/sysv.S +38 -0
  71. data/ext/ffi_c/libffi/src/sparc/ffi.c +16 -0
  72. data/ext/ffi_c/libffi/src/tramp.c +6 -1
  73. data/ext/ffi_c/libffi/src/types.c +23 -1
  74. data/ext/ffi_c/libffi/src/{wasm32 → wasm}/ffi.c +166 -315
  75. data/ext/ffi_c/libffi/src/{wasm32 → wasm}/ffitarget.h +17 -0
  76. data/ext/ffi_c/libffi/src/x86/ffi.c +4 -1
  77. data/ext/ffi_c/libffi/src/x86/ffi64.c +4 -1
  78. data/ext/ffi_c/libffi/src/x86/ffitarget.h +0 -3
  79. data/ext/ffi_c/libffi/src/x86/sysv.S +1 -3
  80. data/ext/ffi_c/libffi/src/x86/sysv_intel.S +1 -3
  81. data/ext/ffi_c/libffi/testsuite/Makefile.am +6 -4
  82. data/ext/ffi_c/libffi/testsuite/Makefile.in +10 -4
  83. data/ext/ffi_c/libffi/testsuite/emscripten/build-tests.sh +4 -24
  84. data/ext/ffi_c/libffi/testsuite/emscripten/build.sh +10 -27
  85. data/ext/ffi_c/libffi/testsuite/emscripten/node-tests.sh +6 -31
  86. data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +269 -256
  87. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/testcases.c +1 -1
  88. data/ext/ffi_c/libffi/testsuite/libffi.call/callback.c +2 -2
  89. data/ext/ffi_c/libffi/testsuite/libffi.call/callback2.c +2 -2
  90. data/ext/ffi_c/libffi/testsuite/libffi.call/callback3.c +2 -2
  91. data/ext/ffi_c/libffi/testsuite/libffi.call/callback4.c +2 -2
  92. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +3 -0
  93. data/ext/ffi_c/libffi/testsuite/libffi.call/longjmp.c +60 -0
  94. data/ext/ffi_c/libffi/testsuite/libffi.call/overread.c +54 -0
  95. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_int_float.c +88 -0
  96. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct2.c +1 -0
  97. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct3.c +1 -0
  98. data/ext/ffi_c/libffi/testsuite/libffi.call/x32.c +31 -0
  99. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_dbls_struct.c +1 -1
  100. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_sshortchar.c +1 -1
  101. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_ushortchar.c +1 -1
  102. data/ext/ffi_c/libffi/testsuite/libffi.closures/huge_struct.c +1 -2
  103. data/ext/ffi_c/libffi/testsuite/libffi.closures/unwindtest.cc +2 -0
  104. data/ext/ffi_c/libffi/testsuite/libffi.closures/unwindtest_ffi_call.cc +2 -0
  105. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_int.c +1 -1
  106. data/ext/ffi_c/libffi/testsuite/libffi.threads/ffitest.h +1 -0
  107. data/ext/ffi_c/libffi/testsuite/libffi.threads/threads.exp +50 -0
  108. data/ext/ffi_c/libffi/testsuite/libffi.threads/tsan.c +74 -0
  109. data/ext/ffi_c/libffi.mk +5 -0
  110. data/ffi.gemspec +4 -5
  111. data/lib/ffi/autopointer.rb +6 -0
  112. data/lib/ffi/compat.rb +11 -0
  113. data/lib/ffi/function.rb +23 -0
  114. data/lib/ffi/library.rb +19 -3
  115. data/lib/ffi/struct_by_reference.rb +1 -1
  116. data/lib/ffi/version.rb +1 -1
  117. data/samples/hello_ractor.rb +9 -1
  118. data/samples/qsort_ractor.rb +9 -1
  119. data/sig/ffi/auto_pointer.rbs +1 -1
  120. data/sig/ffi/errno.rbs +8 -0
  121. data/sig/ffi/platform.rbs +49 -0
  122. data/sig/ffi/struct.rbs +2 -2
  123. data/sig/ffi/struct_by_reference.rbs +1 -1
  124. data/sig/ffi.rbs +4 -1
  125. data.tar.gz.sig +0 -0
  126. metadata +37 -83
  127. metadata.gz.sig +0 -0
  128. data/ext/ffi_c/libffi/.appveyor/site.exp +0 -16
  129. data/ext/ffi_c/libffi/.appveyor.yml +0 -84
  130. data/ext/ffi_c/libffi/.circleci/config.yml +0 -156
  131. data/ext/ffi_c/libffi/src/nios2/ffi.c +0 -304
  132. data/ext/ffi_c/libffi/src/nios2/ffitarget.h +0 -52
  133. data/ext/ffi_c/libffi/src/nios2/sysv.S +0 -136
  134. data/lib/ffi/tools/types_generator.rb +0 -137
  135. data/rakelib/ffi_gem_helper.rb +0 -65
  136. /data/ext/ffi_c/libffi/{.appveyor → .ci}/unix-noexec.exp +0 -0
@@ -21,7 +21,7 @@
21
21
 
22
22
  #include <stdio.h>
23
23
 
24
- FILE* out;
24
+ FILE* out = NULL;
25
25
 
26
26
  #define uchar unsigned char
27
27
  #define ushort unsigned short
@@ -7,9 +7,9 @@
7
7
  /* { dg-do run } */
8
8
  #include "ffitest.h"
9
9
 
10
- int i=5;
10
+ static int i=5;
11
11
 
12
- void callback(void) { i++; }
12
+ static void callback(void) { i++; }
13
13
 
14
14
  typedef struct
15
15
  {
@@ -7,9 +7,9 @@
7
7
  /* { dg-do run } */
8
8
  #include "ffitest.h"
9
9
 
10
- int i=5;
10
+ static int i=5;
11
11
 
12
- void callback(void) { i++; }
12
+ static void callback(void) { i++; }
13
13
 
14
14
  typedef struct
15
15
  {
@@ -7,9 +7,9 @@
7
7
  /* { dg-do run } */
8
8
  #include "ffitest.h"
9
9
 
10
- int i=5;
10
+ static int i=5;
11
11
 
12
- void callback(void) { i++; }
12
+ static void callback(void) { i++; }
13
13
 
14
14
 
15
15
  typedef struct
@@ -7,9 +7,9 @@
7
7
  /* { dg-do run } */
8
8
  #include "ffitest.h"
9
9
 
10
- int i=5;
10
+ static int i=5;
11
11
 
12
- void callback(void) { i++; }
12
+ static void callback(void) { i++; }
13
13
 
14
14
 
15
15
  typedef struct
@@ -1,3 +1,6 @@
1
+ #undef __USE_MINGW_ANSI_STDIO
2
+ #define __USE_MINGW_ANSI_STDIO 1
3
+
1
4
  #include <stdlib.h>
2
5
  #include <stdio.h>
3
6
  #include <string.h>
@@ -0,0 +1,60 @@
1
+ /* Area: ffi_call
2
+ Purpose: Test longjmp over ffi_call frames */
3
+
4
+ /* Test code adapted from Lars Kanis' bug report:
5
+ https://github.com/libffi/libffi/issues/905 */
6
+
7
+ /* { dg-do run } */
8
+
9
+ #include "ffitest.h"
10
+ #include "ffi_common.h"
11
+
12
+ #include <setjmp.h>
13
+
14
+ static jmp_buf buf;
15
+
16
+ static void ABI_ATTR lev2(const char *str) {
17
+ printf("lev2 %s\n", str);
18
+ // jumps back to where setjmp was called - making setjmp now return 1
19
+ longjmp(buf, 1);
20
+ }
21
+
22
+ static void ABI_ATTR lev1(const char *str) {
23
+ lev2(str);
24
+
25
+ // will not be reached
26
+ printf("lev1 %s\n", str);
27
+ }
28
+
29
+ int main()
30
+ {
31
+ ffi_cif cif;
32
+ ffi_type *args[1];
33
+ void *values[1];
34
+ char *s;
35
+ ffi_arg rc;
36
+ /* Initialize the argument info vectors */
37
+ args[0] = &ffi_type_pointer;
38
+ values[0] = &s;
39
+ /* Initialize the cif */
40
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
41
+ &ffi_type_sint, args) == FFI_OK)
42
+ {
43
+ s = "direct call";
44
+ if (!setjmp(buf)){
45
+ // works on x64 and arm64
46
+ lev1(s);
47
+ } else {
48
+ printf("back to main\n");
49
+ }
50
+
51
+ s = "through libffi";
52
+ if (!setjmp(buf)){
53
+ // works on x64 but segfaults on arm64
54
+ ffi_call(&cif, (void (*)(void))lev1, &rc, values);
55
+ } else {
56
+ printf("back to main\n");
57
+ }
58
+ }
59
+ return 0;
60
+ }
@@ -0,0 +1,54 @@
1
+ /* Area: ffi_call
2
+ Purpose: Tests if ffi_call reads data beyond end.
3
+ Limitations: needs mmap.
4
+ PR: 887
5
+ Originator: Mikulas Patocka <mikulas@twibright.com> */
6
+
7
+ /* { dg-do run } */
8
+
9
+ #include "ffitest.h"
10
+
11
+ #ifdef __linux__
12
+ #include <sys/mman.h>
13
+ #include <unistd.h>
14
+
15
+ static int ABI_ATTR fn(unsigned char a, unsigned short b, unsigned int c, unsigned long d)
16
+ {
17
+ return (int)(a + b + c + d);
18
+ }
19
+ #endif
20
+
21
+ int main(void)
22
+ {
23
+ #ifdef __linux__
24
+ ffi_cif cif;
25
+ ffi_type *args[MAX_ARGS];
26
+ void *values[MAX_ARGS];
27
+ ffi_arg rint;
28
+ char *m;
29
+ int ps;
30
+ args[0] = &ffi_type_uchar;
31
+ args[1] = &ffi_type_ushort;
32
+ args[2] = &ffi_type_uint;
33
+ args[3] = &ffi_type_ulong;
34
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 4, &ffi_type_sint, args) == FFI_OK);
35
+ ps = getpagesize();
36
+ m = mmap(NULL, ps * 3, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
37
+ CHECK(m != MAP_FAILED);
38
+ CHECK(mprotect(m, ps, PROT_NONE) == 0);
39
+ CHECK(mprotect(m + ps * 2, ps, PROT_NONE) == 0);
40
+ values[0] = m + ps * 2 - sizeof(unsigned char);
41
+ values[1] = m + ps * 2 - sizeof(unsigned short);
42
+ values[2] = m + ps * 2 - sizeof(unsigned int);
43
+ values[3] = m + ps * 2 - sizeof(unsigned long);
44
+ ffi_call(&cif, FFI_FN(fn), &rint, values);
45
+ CHECK((int)rint == 0);
46
+ values[0] = m + ps;
47
+ values[1] = m + ps;
48
+ values[2] = m + ps;
49
+ values[3] = m + ps;
50
+ ffi_call(&cif, FFI_FN(fn), &rint, values);
51
+ CHECK((int)rint == 0);
52
+ #endif
53
+ exit(0);
54
+ }
@@ -0,0 +1,88 @@
1
+ /* Area: ffi_call
2
+ Purpose: Demonstrate structures with integers corrupting earlier floats
3
+ Limitations: none.
4
+ PR: #848
5
+ Originator: kellda */
6
+
7
+ /* { dg-do run } */
8
+ #include "ffitest.h"
9
+
10
+ typedef struct
11
+ {
12
+ unsigned long i;
13
+ float f;
14
+ } test_structure_int_float;
15
+
16
+ static float ABI_ATTR struct_int_float(test_structure_int_float ts1,
17
+ test_structure_int_float ts2 __UNUSED__,
18
+ test_structure_int_float ts3 __UNUSED__,
19
+ test_structure_int_float ts4 __UNUSED__,
20
+ test_structure_int_float ts5 __UNUSED__,
21
+ test_structure_int_float ts6 __UNUSED__)
22
+ {
23
+ return ts1.f;
24
+ }
25
+
26
+ int main (void)
27
+ {
28
+ ffi_cif cif;
29
+ ffi_type *args[MAX_ARGS];
30
+ void *values[MAX_ARGS];
31
+ ffi_type ts_type;
32
+ ffi_type *ts_type_elements[3];
33
+ float rfloat;
34
+
35
+ test_structure_int_float ts_arg[6];
36
+
37
+ ts_type.size = 0;
38
+ ts_type.alignment = 0;
39
+ ts_type.type = FFI_TYPE_STRUCT;
40
+ ts_type.elements = ts_type_elements;
41
+ ts_type_elements[0] = &ffi_type_ulong;
42
+ ts_type_elements[1] = &ffi_type_float;
43
+ ts_type_elements[2] = NULL;
44
+
45
+ args[0] = &ts_type;
46
+ values[0] = &ts_arg[0];
47
+ args[1] = &ts_type;
48
+ values[1] = &ts_arg[1];
49
+ args[2] = &ts_type;
50
+ values[2] = &ts_arg[2];
51
+ args[3] = &ts_type;
52
+ values[3] = &ts_arg[3];
53
+ args[4] = &ts_type;
54
+ values[4] = &ts_arg[4];
55
+ args[5] = &ts_type;
56
+ values[5] = &ts_arg[5];
57
+
58
+ /* Initialize the cif */
59
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 6, &ffi_type_float, args) == FFI_OK);
60
+
61
+ ts_arg[0].i = 1;
62
+ ts_arg[0].f = 11.11f;
63
+ ts_arg[1].i = 2;
64
+ ts_arg[1].f = 22.22f;
65
+ ts_arg[2].i = 3;
66
+ ts_arg[2].f = 33.33f;
67
+ ts_arg[3].i = 4;
68
+ ts_arg[3].f = 44.44f;
69
+ ts_arg[4].i = 5;
70
+ ts_arg[4].f = 55.55f;
71
+ ts_arg[5].i = 6;
72
+ ts_arg[5].f = 66.66f;
73
+
74
+ printf ("%g\n", ts_arg[0].f);
75
+ printf ("%g\n", ts_arg[1].f);
76
+ printf ("%g\n", ts_arg[2].f);
77
+ printf ("%g\n", ts_arg[3].f);
78
+ printf ("%g\n", ts_arg[4].f);
79
+ printf ("%g\n", ts_arg[5].f);
80
+
81
+ ffi_call(&cif, FFI_FN(struct_int_float), &rfloat, values);
82
+
83
+ printf ("%g\n", rfloat);
84
+
85
+ CHECK(fabs(rfloat - 11.11) < 3 * FLT_EPSILON);
86
+
87
+ exit(0);
88
+ }
@@ -33,6 +33,7 @@ test_fn (int n, ...)
33
33
  struct small_tag s2;
34
34
  struct large_tag l;
35
35
 
36
+ (void) n;
36
37
  va_start (ap, n);
37
38
  s1 = va_arg (ap, struct small_tag);
38
39
  l = va_arg (ap, struct large_tag);
@@ -33,6 +33,7 @@ test_fn (int n, ...)
33
33
  struct small_tag s2;
34
34
  struct large_tag l;
35
35
 
36
+ (void) n;
36
37
  va_start (ap, n);
37
38
  s1 = va_arg (ap, struct small_tag);
38
39
  l = va_arg (ap, struct large_tag);
@@ -0,0 +1,31 @@
1
+ /* Area: ffi_call
2
+ Purpose: Check zero-extension of pointers on x32.
3
+ Limitations: none.
4
+ PR: 887
5
+ Originator: Mikulas Patocka <mikulas@twibright.com> */
6
+
7
+ /* { dg-do run } */
8
+
9
+ #include "ffitest.h"
10
+
11
+ static int ABI_ATTR fn(int *a)
12
+ {
13
+ if (a)
14
+ return *a;
15
+ return -1;
16
+ }
17
+
18
+ int main(void)
19
+ {
20
+ ffi_cif cif;
21
+ ffi_type *args[MAX_ARGS];
22
+ void *values[MAX_ARGS];
23
+ void *z[2] = { (void *)0, (void *)1 };
24
+ ffi_arg rint;
25
+ args[0] = &ffi_type_pointer;
26
+ values[0] = z;
27
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ffi_type_sint, args) == FFI_OK);
28
+ ffi_call(&cif, FFI_FN(fn), &rint, values);
29
+ CHECK((int)rint == -1);
30
+ exit(0);
31
+ }
@@ -28,7 +28,7 @@ closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
28
28
  closure_test_fn(*(Dbls*)args[0]);
29
29
  }
30
30
 
31
- int main(int argc __UNUSED__, char** argv __UNUSED__)
31
+ int main(void)
32
32
  {
33
33
  ffi_cif cif;
34
34
 
@@ -80,7 +80,7 @@ int main (void)
80
80
  /* { dg-output "1 32765 127 -128: 32765" } */
81
81
  printf("res: %d\n", (signed short)res_call);
82
82
  /* { dg-output "\nres: 32765" } */
83
- CHECK(res_call == 32765);
83
+ CHECK((signed short)res_call == 32765);
84
84
 
85
85
  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK);
86
86
 
@@ -80,7 +80,7 @@ int main (void)
80
80
  /* { dg-output "1 2 127 128: 258" } */
81
81
  printf("res: %d\n", (unsigned short)res_call);
82
82
  /* { dg-output "\nres: 258" } */
83
- CHECK(res_call == 258);
83
+ CHECK((unsigned short)res_call == 258);
84
84
 
85
85
  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK);
86
86
 
@@ -216,8 +216,7 @@ cls_large_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __
216
216
  ui8_5, si8_5);
217
217
  }
218
218
 
219
- int
220
- main(int argc __UNUSED__, const char** argv __UNUSED__)
219
+ int main (void)
221
220
  {
222
221
  void *code;
223
222
  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
@@ -48,7 +48,9 @@ typedef int (*closure_test_type1)(float, float, float, float, signed short,
48
48
  float, float, int, double, int, int, float,
49
49
  int, int, int, int);
50
50
 
51
+ #ifdef __EMSCRIPTEN__
51
52
  extern "C"
53
+ #endif
52
54
  int main (void)
53
55
  {
54
56
  ffi_cif cif;
@@ -14,7 +14,9 @@ static int checking(int a __UNUSED__, short b __UNUSED__,
14
14
  throw 9;
15
15
  }
16
16
 
17
+ #ifdef __EMSCRIPTEN__
17
18
  extern "C"
19
+ #endif
18
20
  int main (void)
19
21
  {
20
22
  ffi_cif cif;
@@ -76,7 +76,7 @@ int main (void)
76
76
 
77
77
  printf ("%d,%di %d,%di, x %d 1234, y %d 11110\n",
78
78
  (int)tc_result, (int)(tc_result * -I), 2, 8, tc_int_arg_x, tc_y);
79
- /* dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" */
79
+ /* { dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" } */
80
80
  CHECK (creal (tc_result) == -2);
81
81
  CHECK (cimag (tc_result) == 8);
82
82
  CHECK (tc_int_arg_x == 1234);
@@ -0,0 +1 @@
1
+ #include "../libffi.call/ffitest.h"
@@ -0,0 +1,50 @@
1
+ # Copyright (C) 2003, 2006, 2009, 2010, 2014 Free Software Foundation, Inc.
2
+
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program; see the file COPYING3. If not see
15
+ # <http://www.gnu.org/licenses/>.
16
+
17
+ dg-init
18
+ libffi-init
19
+
20
+ global srcdir subdir
21
+
22
+ if { [string match $compiler_vendor "microsoft"] } {
23
+ # -wd4005 macro redefinition
24
+ # -wd4244 implicit conversion to type of smaller size
25
+ # -wd4305 truncation to smaller type
26
+ # -wd4477 printf %lu of uintptr_t
27
+ # -wd4312 implicit conversion to type of greater size
28
+ # -wd4311 pointer truncation to unsigned long
29
+ # -EHsc C++ Exception Handling (no SEH exceptions)
30
+ set additional_options "-wd4005 -wd4244 -wd4305 -wd4477 -wd4312 -wd4311 -EHsc";
31
+ } else {
32
+ set additional_options "";
33
+ }
34
+
35
+ set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.c]]
36
+
37
+ # No pthreads for windows or wasm
38
+ if { [string match $compiler_vendor "microsoft"] || [istarget "wasm*-*-*"] } {
39
+ foreach test $tlist {
40
+ unsupported "$test"
41
+ }
42
+ } else {
43
+ run-many-tests $tlist $additional_options
44
+ }
45
+
46
+ dg-finish
47
+
48
+ # Local Variables:
49
+ # tcl-indent-level:4
50
+ # End:
@@ -0,0 +1,74 @@
1
+ /* { dg-do run } */
2
+
3
+ #include "ffitest.h"
4
+
5
+ #include <pthread.h>
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+
9
+ #define NUM_THREADS 20
10
+
11
+ #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
12
+ pthread_barrier_t barrier;
13
+ #endif
14
+
15
+ typedef float (*callback_fn)(float, float);
16
+
17
+ void callback(ffi_cif *cif __UNUSED__, void *ret, void **args, void *userdata __UNUSED__) {
18
+ float a = *(float *)args[0];
19
+ float b = *(float *)args[1];
20
+ *(float *)ret = a / 2 + b / 2;
21
+ }
22
+
23
+ void *thread_func(void *arg) {
24
+ #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
25
+ pthread_barrier_wait(&barrier);
26
+ #endif
27
+
28
+ ffi_cif cif;
29
+ ffi_type *args[2] = { &ffi_type_float, &ffi_type_float };
30
+
31
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_float, args) != FFI_OK) {
32
+ fprintf(stderr, "ffi_prep_cif failed\n");
33
+ return NULL;
34
+ }
35
+
36
+ ffi_closure *closure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&arg);
37
+
38
+ if (ffi_prep_closure_loc(closure, &cif, callback, NULL, arg) != FFI_OK) {
39
+ fprintf(stderr, "ffi_prep_closure_loc failed\n");
40
+ return NULL;
41
+ }
42
+
43
+ callback_fn fn = (callback_fn)arg;
44
+ (void) fn(4.0f, 6.0f);
45
+
46
+ ffi_closure_free(closure);
47
+ return NULL;
48
+ }
49
+
50
+ int main() {
51
+ pthread_t threads[NUM_THREADS];
52
+
53
+ #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
54
+ pthread_barrier_init(&barrier, NULL, NUM_THREADS);
55
+ #endif
56
+
57
+ for (int i = 0; i < NUM_THREADS; ++i) {
58
+ if (pthread_create(&threads[i], NULL, thread_func, NULL) != 0) {
59
+ perror("pthread_create");
60
+ exit(EXIT_FAILURE);
61
+ }
62
+ }
63
+
64
+ for (int i = 0; i < NUM_THREADS; ++i) {
65
+ pthread_join(threads[i], NULL);
66
+ }
67
+
68
+ #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
69
+ pthread_barrier_destroy(&barrier);
70
+ #endif
71
+
72
+ printf("Completed\n");
73
+ return 0;
74
+ }
data/ext/ffi_c/libffi.mk CHANGED
@@ -16,3 +16,8 @@ $(LIBFFI):
16
16
  sh $(LIBFFI_CONFIGURE) $(LIBFFI_HOST) > /dev/null; \
17
17
  fi
18
18
  $(MAKE) -C "$(LIBFFI_BUILD_DIR)"
19
+
20
+ install: install-cleanup
21
+
22
+ install-cleanup: $(DLLIB)
23
+ rm -rf "$(LIBFFI_BUILD_DIR)"
data/ffi.gemspec CHANGED
@@ -15,9 +15,10 @@ Gem::Specification.new do |s|
15
15
  s.metadata['wiki_uri'] = 'https://github.com/ffi/ffi/wiki'
16
16
  s.metadata['source_code_uri'] = 'https://github.com/ffi/ffi/'
17
17
  s.metadata['mailing_list_uri'] = 'http://groups.google.com/group/ruby-ffi'
18
+ s.metadata['rubygems_mfa_required'] = 'true'
18
19
  end
19
20
  s.files = `git ls-files -z`.split("\x0").reject do |f|
20
- f =~ /^(\.|bench|gen|libtest|nbproject|spec)/
21
+ f =~ /^(\.|bench|gen|libtest|nbproject|spec|rakelib)/
21
22
  end
22
23
 
23
24
  # Add libffi git files
@@ -35,8 +36,6 @@ Gem::Specification.new do |s|
35
36
  s.license = 'BSD-3-Clause'
36
37
  s.require_paths << 'ext/ffi_c'
37
38
  s.required_ruby_version = '>= 2.5'
38
- s.add_development_dependency 'rake', '~> 13.0'
39
- s.add_development_dependency 'rake-compiler', '~> 1.1'
40
- s.add_development_dependency 'rake-compiler-dock', '~> 1.0'
41
- s.add_development_dependency 'rspec', '~> 2.14.1'
39
+
40
+ s.metadata['msys2_mingw_dependencies'] = 'libffi'
42
41
  end
@@ -89,6 +89,12 @@ module FFI
89
89
  self
90
90
  end
91
91
 
92
+ def dup
93
+ raise RuntimeError, "cannot duplicate FFI::AutoPointer"
94
+ end
95
+
96
+ alias clone dup
97
+
92
98
  # @return [nil]
93
99
  # Free the pointer.
94
100
  def free
data/lib/ffi/compat.rb CHANGED
@@ -40,4 +40,15 @@ module FFI
40
40
  obj.freeze
41
41
  end
42
42
  end
43
+
44
+ if defined?(Ractor.shareable_proc)
45
+ # This is for FFI internal use only.
46
+ def self.shareable_proc(**kwargs, &block)
47
+ Ractor.shareable_proc(**kwargs, &block)
48
+ end
49
+ else
50
+ def self.shareable_proc(**_kwargs, &block)
51
+ block
52
+ end
53
+ end
43
54
  end
data/lib/ffi/function.rb CHANGED
@@ -51,6 +51,29 @@ module FFI
51
51
  end
52
52
  end
53
53
 
54
+ if RUBY_PLATFORM == 'aarch64-mingw-ucrt'
55
+ # Use a workaround for https://github.com/libffi/libffi/issues/905
56
+ def attach(mod, name)
57
+ this = self
58
+ body = proc do |*args, &block|
59
+ this.call(*args, &block)
60
+ end
61
+
62
+ mod.define_method(name, body)
63
+ mod.define_singleton_method(name, body)
64
+
65
+ # Store function Proc's for re-definition as Ractor-shareable in Library#freeze
66
+ funcs = mod.instance_variable_get("@ffi_function_procs")
67
+ unless funcs
68
+ funcs = {}
69
+ mod.instance_variable_set("@ffi_function_procs", funcs)
70
+ end
71
+ funcs[name] = self
72
+
73
+ self
74
+ end
75
+ end
76
+
54
77
  # Stash the Function in a module variable so it can be inspected by attached_functions.
55
78
  # On CRuby it also ensures that it does not get garbage collected.
56
79
  module RegisterAttach
data/lib/ffi/library.rb CHANGED
@@ -287,7 +287,7 @@ module FFI
287
287
  if type.is_a?(Class) && type < FFI::Struct
288
288
  # If it is a global struct, just attach directly to the pointer
289
289
  s = s = type.new(address) # Assigning twice to suppress unused variable warning
290
- self.module_eval <<-code, __FILE__, __LINE__
290
+ self.module_eval(<<-code, __FILE__, __LINE__)
291
291
  @ffi_gsvars = {} unless defined?(@ffi_gsvars)
292
292
  @ffi_gsvars[#{mname.inspect}] = s
293
293
  def self.#{mname}
@@ -302,7 +302,7 @@ module FFI
302
302
  #
303
303
  # Attach to this module as mname/mname=
304
304
  #
305
- self.module_eval <<-code, __FILE__, __LINE__
305
+ self.module_eval(<<-code, __FILE__, __LINE__)
306
306
  @ffi_gvars = {} unless defined?(@ffi_gvars)
307
307
  @ffi_gvars[#{mname.inspect}] = s
308
308
  def self.#{mname}
@@ -564,12 +564,28 @@ module FFI
564
564
  # Freeze all definitions of the module
565
565
  #
566
566
  # This freezes the module's definitions, so that it can be used in a Ractor.
567
- # No further methods or variables can be attached and no further enums or typedefs can be created in this module afterwards.
567
+ # No further functions or variables can be attached and no further enums or typedefs can be created in this module afterwards.
568
568
  def freeze
569
+ # @ffi_function_procs is only used on aarch64-mingw-ucrt
570
+ instance_variable_get("@ffi_function_procs")&.each do |name, func|
571
+ # Redefine attached functions as Ractor-shareable.
572
+ # The function Proc can't be shareable from the beginning, since it references enums and typedefs.
573
+ this = FFI.make_shareable(func)
574
+ body = FFI.shareable_proc(self: nil) do |*args, &block|
575
+ this.call(*args, &block)
576
+ end
577
+ undef_method(name)
578
+ singleton_class.undef_method(name)
579
+
580
+ define_method(name, body)
581
+ define_singleton_method(name, body)
582
+ end
583
+
569
584
  instance_variables.each do |name|
570
585
  var = instance_variable_get(name)
571
586
  FFI.make_shareable(var)
572
587
  end
588
+ super
573
589
  nil
574
590
  end
575
591
  end
@@ -44,7 +44,7 @@ module FFI
44
44
  end
45
45
 
46
46
  # Always get {FFI::Type}::POINTER.
47
- def native_type
47
+ def native_type(_type = nil)
48
48
  FFI::Type::POINTER
49
49
  end
50
50